06 Feb 2017
|
jpa
spring
springboot
springdata
iBatis만 사용하다가 SpringData를 처음 접해보면 신세계를 느끼는 것 중 하나가 interface에 메소드 하나 정의 했는데 쿼리가 완성된다는 점이 아닐까 싶습니다.
xml에 죽어라 SQL문 만들다가 이렇게 간단하게 해결되면 SpringData를 안쓸수가 없죠.(반대로 더 불편해지거나 힘든점도 있긴 합니다.)
그동안 사용해온 쿼리 메소드들에 대해 몇몇가지 정리해봅니다.
자세한 내용은 Spring Data JPA - Reference Documentation(1.10.7)영문이나 이쁘게 번역해놓은 번역본을 참고하시기 바랍니다.
메소드 이름 안에서 지원되는 키워드들
Keyword |
Sample |
JPQL snippet |
And |
findByLastnameAndFirstname |
… where x.lastname = ?1 and x.firstname = ?2 |
Or |
findByLastnameOrFirstname |
… where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals |
findByFirstname,findByFirstnameIs,findByFirstnameEquals |
… where x.firstname = 1? |
Between |
findByStartDateBetween |
… where x.startDate between 1? and ?2 |
LessThan |
findByAgeLessThan |
… where x.age < ?1 |
LessThanEqual |
findByAgeLessThanEqual |
… where x.age ⇐ ?1 |
GreaterThan |
findByAgeGreaterThan |
… where x.age > ?1 |
GreaterThanEqual |
findByAgeGreaterThanEqual |
… where x.age >= ?1 |
After |
findByStartDateAfter |
… where x.startDate > ?1 |
Before |
findByStartDateBefore |
… where x.startDate < ?1 |
IsNull |
findByAgeIsNull |
… where x.age is null |
IsNotNull,NotNull |
findByAge(Is)NotNull |
… where x.age not null |
Like |
findByFirstnameLike |
… where x.firstname like ?1 |
NotLike |
findByFirstnameNotLike |
… where x.firstname not like ?1 |
StartingWith |
findByFirstnameStartingWith |
… where x.firstname like ?1 (parameter bound with appended %) |
EndingWith |
findByFirstnameEndingWith |
… where x.firstname like ?1 (parameter bound with prepended %) |
Containing |
findByFirstnameContaining |
… where x.firstname like ?1 (parameter bound wrapped in %) |
OrderBy |
findByAgeOrderByLastnameDesc |
… where x.age = ?1 order by x.lastname desc |
Not |
findByLastnameNot |
… where x.lastname <> ?1 |
In |
findByAgeIn(Collection ages) |
… where x.age in ?1 |
NotIn |
findByAgeNotIn(Collection age) |
… where x.age not in ?1 |
True |
findByActiveTrue() |
… where x.active = true |
False |
findByActiveFalse() |
… where x.active = false |
IgnoreCase |
findByFirstnameIgnoreCase |
… where UPPER(x.firstame) = UPPER(?1) |
쿼리 결과 Limit(Top)하기
User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
Slice<User> findTop3ByLastname(String lastname, Pageable pageable);
List<User> findFirst10ByLastname(String lastname, Sort sort);
List<User> findTop10ByLastname(String lastname, Pageable pageable);
중복제거 Disctinct 사용하기
List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);
05 Feb 2017
|
springboot
webmvctest
junit
WebMvcTest
AutoConfigureMockMvc
SpringBoot Reference에 접속하여 목차를 보면 거의 끝쯤에 Testing관련 내용이 나옵니다.
이 중 SpringBoot의 Controller를 JUnit으로 테스트 하고 싶은 경우 41.3.7 Auto-configured Spring MVC tests를 보면 Http Connection을 별도 구현하지 않고도 MVC 테스트를 가능하게 하는 설명이 나옵니다.
@WebMvcTest
일반적으로 사용하는 MVC테스트용 어노테이션입니다.
해당 어노테이션을 명시하고 그림과 같이 MockMvc
를 @Autowired
하면 해당 객체를 통해 MVC테스트가 가능합니다.
@WebMvcTest
어노테이션 사용시 @SpringBootTest
을 같이 사용할 수 없습니다.
서로 MockMvc
를 설정하기 때문에 충돌이 나는거 같은데요, MVC 기능만 사용할 거라면 @WebMvcTest
를 사용하면 됩니다.
@WebMvcTest
사용시 다른 설정들은 자동으로 올리지 않기 때문에 @Repository
나 @Resource
, @Service
, @Component
등은 사용할 수 없습니다.
아래 글과 같이 자동설정하는 영역은 @Controller
, @ControllerAdvice
, @JsonComponent
등등이네요.
그런데 저는 실제로 테스트 해보니 @ControllerAdvice
도 먹히지 않았습니다. (이유는 아직도 모르는중…)
@WebMvcTest
가 포함하는 실제 설정은 Appendix D. Test auto-configuration annotations에서 확인 가능 합니다.
@WebMvcTest
외에 MVC테스트를 할 수 있는 다른 방법입니다.
위 설정은 MVC테스트 외 모든 설정을 같이 올립니다. AOP도 되고 JPA Repository도 사용가능하네요.
실제적으로 동작하는 MVC테스트를 하려면 위 어노테이션을 사용해야 합니다.
@AutoConfigureMockMvc
은 @SpringBootTest
와 같이 사용 가능합니다.
04 Feb 2017
|
springboot
h2
dbeaver
SpringBoot에서 H2 DB Embedded를 사용하다보면 항상 console에 들어가 쿼리해야하는 불편함이 있어 외부 툴에서 접근하는 방법을 찾아 정리해 보았습니다.
우선 application.xml에 정의되 있는 아래 항목을 바꿔줍니다.
[변경 전]
spring.datasource.url=jdbc:h2:file:./db/devdb;
[변경 후]
spring.datasource.url=jdbc:h2:file:./db/devdb;AUTO_SERVER=TRUE
※ 주의사항 : H2 DB를 메모리 모드로 올릴 경우에는 사용 할 수 없습니다. 반드시 file모드로 올려주세요.
위와 같이 변경후 실행 시키면 서버모드로 뜨게 되고 DBeaver를 통해 아래와 같이 설정합니다.
- “Create New Connect” 창을 띄우고 아래와 같이 “H2 - Embedded”를 선택합니다.
- Setting 화면에 아래와 같이 각 정보를 넣어줍니다.
※ JDBC URL 항목이 빈 란일 경우 “Driver Properties”탭을 선택하여 H2 Driver를 다운 받았는지 확인합니다.
※ 파일 경로를 full로 적어줘야합니다.
위와 같이 설정해도 한쪽에서 붙어 있는 상황에선 다른쪽이 붙질 못하더군요.
그 방법까진 아직 못찾아봐서 패스.
03 Feb 2017
|
jpa
date
spring
springboot
springdata
JPA를 사용할때 Date타입의 컬럼 사용시 어떤 Java Object를 사용해야하는지에 대한 글이 있어 옮겨 적어봅니다. 원본보기
java.sql.Date, java.sql.Time, java.sql.Timestamp
@Column(name = "DATE_FIELD")
private java.sql.Date dateField;
@Column(name = "TIME_FIELD")
private java.sql.Time timeField;
@Column(name = "DATETIME_FIELD")
private java.sql.Timestamp dateTimeField;
@Column(name = "TIMESTAMP_FIELD")
private java.sql.Timestamp timestampField;
응용 프로그램이 날짜 및 시간 값을 저장하기만 해도 될 경우 사용합니다.
서버 GMT 오프셋과 같이 날짜 및 시간의 확장 된 세부 정보를 저장하거나 다른 지역 또는 시간대에 다른 날짜와 시간을 저장하지 않아도 될 경우에 좋습니다.
java.util.Date
@Temporal(TemporalType.DATE)
@Column(name = "DATE_FIELD")
private java.util.Date dateField;
@Temporal(TemporalType.TIME)
@Column(name = "TIME_FIELD")
private java.util.Date timeField;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "DATETIME_FIELD")
private java.util.Date dateTimeField;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "TIMESTAMP_FIELD")
private java.util.Date timestampField;
프로그램의 날짜와 GMT값을 날짜,시간,타임스템프 필드와 함꼐 저장해야하는 경우에 사용합니다.
java.util.Date 클래스는 날짜와 시간 정보를 모두 저장할 수 있기 때문에 올바른 TemporalType 속성 (TemporalType.DATE, TemporalType.TIME 또는 TemporalType.TIMESTAMP)이있는 @Temporal 주석이 추가로 필요합니다.
java.util.Calendar
@Column(name = "DATE_FIELD")
@Temporal(TemporalType.DATE)
private java.util.Calendar dateField;
@Column(name = "TIME_FIELD")
@Temporal(TemporalType.TIME)
private java.util.Calendar timeField;
@Column(name = "DATETIME_FIELD")
@Temporal(TemporalType.TIMESTAMP)
private java.util.Calendar datetimeField;
@Column(name = "TIMESTAMP_FIELD")
@Temporal(TemporalType.TIMESTAMP)
private java.util.Calendar timestampField;
국제 날짜및 시간정보 캡처가 필요한 경우 사용하면 좋습니다.
java.util.Date 클래스와 마찬가지로 @Temporal주석이 필요합니다.
일반적으로 개발할때는 java.sql.Timestamp만 사용해도 충분하겠네요 :)
02 Feb 2017
|
normalization
정규화란?
데이터베이스의 설계에서 중복을 최소화 하게 데이터를 구조화
정규화의 목표
- 데이터의 삽입,삭제,갱신 이상 제거
- 자료저장 공간 최소화
정규화 단계
제1정규화(1NF)
- 모든 속성은 반드시 하나의 값을 가짐(not null, 반복형태 X).
- 레코드들은 서로 간에 식별 가능해야 합니다..
제2정규화(2NF)
- 식별자가 아닌 모든 속성들은 식별자 전체 속성에 완전 종속되어야 합니다(완전함수종속).
제3정규화(3NF)
- 2차 정규형을 만족하고 식별자를 제외한 나머지 속성들 간의 종속이 존재하면 안됩니다.
예제