1
2
3
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByName(String name);
}
- Query Method란 위의 코드처럼 메소드의 이름으로 쿼리를 생성해주는 기능이다.
- Spring Data Jpa가 메소드 이름을 분석해 JPQL을 생성해 실행해준다.
KeyWord
보통 select Query만 많이 사용하고 나머지는 select로 조회한 것을 사용해 처리하거나 Delete같은 경우 Jpa에서 제공하는 Method를 많이 사용한다.
- Select Query
- find…By, read…By, get…By, query…By, search…By, stream…By
- 위의 접두어 모두 같은 역할을 수행하고 일반적으로 findBy를 가장 많이 사용한다.
- …은 Entity가 들어갈 수 있는것을 의미한다.
- ex) findUserByName or findUsersByName
- List반환 일 경우 s를 붙여 사용한다.
- 하지만 보통 Repository를 정의할 때 JpaRepository<User, Long> 으로 Entity명시를 해주기 때문에 많이 사용하지는 않는다.
- ex) findUserByName or findUsersByName
- delete Query
- delete…By, remove…By
- limit
- …First
..., ...Top ... - ex) List
findTop6ByName(String name) - Name으로 조회 했을 때 상위 6개만 조회
- …First
- ETC..
- exists…By
- count…By
After, Before
1
2
3
4
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByCreatedAtAfter(LocalDateTime day);
List<User> findByCreatedAtBefore(LocalDateTime day);
}
- 생성되는 Query가 특정 column에 대해 param보다 크거나 작은지를 비교하기 때문에 시간이 아닌 경우에도 대소 비교가 가능한 Data라면 사용이 가능하다.
- 시간 비교이외에는 Before, After가 가독성 측면에서 별로 좋지 않아 다른 Data에는 사용이 권장되지 않는다.
데이터 범위
- Greater, Less
1 2 3 4 5 6
public interface UserRepository extends JpaRepository<User, Long> { List<User> findByCreatedAtGreaterThan(LocalDateTime day); List<User> findByCreatedAtGreaterThanEqual(LocalDateTime day); List<User> findByCreatedAtLessThan(LocalDateTime day); List<User> findByCreatedAtLessThanEqual(LocalDateTime day); }
- Between
1 2 3 4
public interface UserRepository extends JpaRepository<User, Long> { List<User> findByCreatedAtBetween(LocalDateTime day1, LocalDateTime day2); List<User> findByIdBetween(Long id1, Long id2); }
- 양 끝의 값을 포함해 사이의 값인 경우 조회 된다.
데이터의 유무
IS_EMPTY, IS_NOT_EMPTY
1 2 3 4 5 6 7 8
... @Entity public class User { ... @OneToMany(fetch = FetchType.EAGER) private List<Address> address; }
1 2
List<User> findByAddressIsNotEmpty(); List<User> findByAddressIsEmpty();
- Collection property에만 사용할 수 있다.
IS_NULL, IS_NOT_NULL
1 2
List<User> findByNameIsNotNull(); List<User> findByNameIsNull();
- 값 자체가 Null인지 아닌지 파악할 때 사용할 수 있다.
In, NotIn
1 2
List<User> findByNameIn(List<String> names); List<User> findByNameNotIn(List<String> names);
문자열 Query
StartingWith, EndingWith, Containing, Like
1 2 3 4
List<User> findByNameStartingWith(String name); // 시작하는 List<User> findByNameEndingWith(String name); // 끝나는 List<User> findByNameContaining(String name); // 포함하는 List<User> findByNameLike(String name);
- 앞의 3개 KeyWord는 like를 한번 Wrapping한것이다.
1 2 3
userRepository.findByNameLike("km%"); // StartingWith("km")과 같다. userRepository.findByNameLike("%ms"); // EndingWith("ms")와 같다. userRepository.findByNameLike("%m%"); // Containing("m")과 같다.
limit
1
List<User> findTop1ByNameOrderByIdDesc(String name);
- Top1을 통해 가장 앞의 하나는 가져올 수 있지만 Last keyword가 없기 때문에 OrderBy를 사용해야한다.
- Id를 역순으로 정렬한 뒤 name이 일치하는 것 중 가장 처음 값을 반환한다.
정렬
- Query Method만 사용
1
List<User> findFirstByNameOrderByIdDescEmailAsc(String name);
- 가장 앞의 조건이 1순위 이며 1순위가 같으면 다음 순위의 조건 기준으로 정렬한다.
- 위의 QueryMethod는 Id 내림차순, Email 오름차순으로 정렬한 뒤 param과 일치하는 가장 처음의 entity를 반환한다.
- Method명이 길어져서 가독성이 안좋아질 수 있다.
- Sort 사용
1
List<User> findFirstByName(String name, Sort sort);
1
userRepository.findFirstByName("kms", Sort.by(Sort.Order.desc("id"), Sort.Order.asc("email")));
- Sort기준을 Parameter로 받아서 사용할 수 있다.
페이징
- Paging의 경우 JpaRespository interface를 사용하면 별도의 코드없이 사용 할 수 있다.
- Page Interface의 경우 Slice를 상속받아 구현 되어 있다. Slice는 Data의 일부분을 가지는 Class이다.
- Pageable은 Page를 요청하는 요청 값이다.
1
Page<User> findByName(String name, Pageable pageable);
사용 코드
1
userRepository.findByName("kms", PageRequest.of(0, 1, Sort.by(Sort.Order.desc("id"))));
- Name이 kms인 entity를 id역순으로 정렬한 뒤 Page당 Entity개수 1개로 나누었을 때 0번째 page를 반환한다.
- getContent()를 통해 Page객체의 값을 사용할 수 있다.
Native Query
Query Method로 이름을 정하기 애매한 경우가 있을 수 있다. 이런경우 직접 DB의 Query문을 작성해 사용할 수 있다.
1 2 3 4 5
// Entity Type, PK Type public interface UserRepository extends JpaRepository<User, Long> { @Query(value = "select * from user where name = 'kms';", nativeQuery = true) Map<String, Object> findWithNativeQuery(); }