쿼리 메서드는 크게 동작을 결정하는 주제(Subject)과 서술어(Predicate)로 구분한다.
'By'는 서술어의 시작을 나타내는 구분자의 역할을 한다.
서술어 부분은 검색 및 정렬 조건을 지정하는 영역이다.
AND나 OR를 사용해 조건을 확장하는 것도 가능하다.
// (리턴타입) + {주제 + 서술어(속성)} 구조의 메서드
List<Person> findByLastnameAndEmail(String lastName, String email);
서술어에 들어가는 엔티티의 속성식은 엔티티에서 관리하고 있는 속성(필드)만 참조할 수 있다.
도메인(엔티티) 표현 가능 : ...로 표시한 영역
- find...By
read...By
get...By
query...By
search...By
stream...By- exists...By : 특정 데이터가 존재하는지 확인 하는 키워드 (리턴 type: boolean)
- count...By : 조회 쿼리를 수행한 후 쿼리 결과로 나온 레코드의 개수를 리턴한다.
- delete...By, remove...By: 삭제 쿼리를 수행한다. 리턴타입이 없거나 삭제한 횟수를 리턴한다.
- ...First< number >..., ...Top< number >...: 쿼리를 통해 조회된 결괏값의 개수를 제한하는 키워드. 한번의 동작으로 여러 건을 조회할때 사용. 단 건으로 조회하기 위해서는 < number >를 생략하면 된다.
EX) 쿼리 메서드
// find..By (예제 8.1)
Optional<Product> findByNumber(Long number);
List<Product> findAllByName(String name);
Product queryByNumber(Long number);
// exists..By (예제 8.2)
boolean existsByNumber(Long number);
// count..By (예제 8.3)
long countByName(String name);
// delete..By, remove..By (예제 8.4)
void deleteByNumber(Long number);
long removeByName(String name);
// …First<number>…, …Top<number>… (예제 8.5)
List<Product> findFirst5ByName(String name);
List<Product> findTop10ByName(String name);
- Is : 값의 일치를 조건으로 사용하는 조건자 키워드, 생략되는 경우 많음, Equals와 동일한 기능 수행
- (Is)Not : 값의 불일치를 조건으로 사용하는 조건자 키워드, Is생략하고 Not키워드만 사용할 수 도 있다
- (Is)Null, (Is)NotNull : 값이 null인지 검사하는 조건자 키워드
- (Is)True, (Is)False : boolean타입으로 지정된 칼럼값을 확인하는 키워드
- And, Or : 여러 조건을 묶을 때 사용
- (Is)GreaterThan, (Is)LessThan, (Is)Between : 숫자나 datetime 칼럼을 대상으로 한 비교 연산에 사용할 수 있는 조건자 키워드, 비교 대상에 대한 초과/미만의 개념으로 비교 연산 수행. 경곗값을 포함하려면 Equal키워드 추가하면 된다
- (Is)StartingWith(==StartsWith), (Is)EndingWith(==EndsWith), (Is)Containing(==Contains), (Is)Like : 컬럼값에서 일부 일치 여부를 확인하는 조건자 키워드, SQL쿼리문에서 '%'키워드와 동일한 역할을 한다
EX) 쿼리 메서드
/* 쿼리 메소드의 조건자 키워드 */
// Is, Equals (생략 가능) (예제 8.6)
// Logical Keyword : IS , Keyword Expressions : Is, Equals, (or no keyword)
// findByNumber 메소드와 동일하게 동작
Product findByNumberIs(Long number);
Product findByNumberEquals(Long number);
// (Is)Not (예제 8.7)
Product findByNumberIsNot(Long number);
Product findByNumberNot(Long number);
// (Is)Null, (Is)NotNull (예제 8.8)
List<Product> findByUpdatedAtNull();
List<Product> findByUpdatedAtIsNull();
List<Product> findByUpdatedAtNotNull();
List<Product> findByUpdatedAtIsNotNull();
// And, Or (예제 8.10)
Product findByNumberAndName(Long number, String name);
Product findByNumberOrName(Long number, String name);
// (Is)GreaterThan, (Is)LessThan, (Is)Between (예제 8.11)
List<Product> findByPriceIsGreaterThan(Long price);
List<Product> findByPriceGreaterThan(Long price);
List<Product> findByPriceGreaterThanEqual(Long price);
List<Product> findByPriceIsLessThan(Long price);
List<Product> findByPriceLessThan(Long price);
List<Product> findByPriceLessThanEqual(Long price);
List<Product> findByPriceIsBetween(Long lowPrice, Long highPrice);
List<Product> findByPriceBetween(Long lowPrice, Long highPrice);
// (Is)Like, (Is)Containing, (Is)StartingWith, (Is)EndingWith (예제 8.12)
List<Product> findByNameLike(String name);
List<Product> findByNameIsLike(String name);
List<Product> findByNameContains(String name);
List<Product> findByNameContaining(String name);
List<Product> findByNameIsContaining(String name);
List<Product> findByNameStartsWith(String name);
List<Product> findByNameStartingWith(String name);
List<Product> findByNameIsStartingWith(String name);
List<Product> findByNameEndsWith(String name);
List<Product> findByNameEndingWith(String name);
List<Product> findByNameIsEndingWith(String name);
기본 쿼리 메서드를 작성한 후 OrderBy키워드를 삽입하고 정렬하고자 하는 컬럼과 오름차순/내림차순을 설정하면 정렬이 수행된다.
정렬 구문은 And나 Or키워드 사용하지 않고, 우선순위를 기준으로 차례대로 작성하면 된다.
// Asc: 오름차순, Desc : 내림차순
List<Product> findByNameOrderByNumberAsc(String name);
List<Product> findByNameOrderByNumberDesc(String name);
// And를 붙이지 않음
List<Product> findByNameOrderByPriceAscStockDesc(String name);
데이터베이스의 레코드를 개수로 나눠 페이지를 구분하는 것을 의미
EX) 페이징 처리위한 쿼리 메서드 예시
Page<Product> findByName(String name, Pageable pageable);
메서드 호출할때, 리턴 타입으로 Page객체 받아야한다.
Pageable파라미터를 전달하기 위해 PageRequest클래스 사용한다.
PageRequest는 Pageable의 구현체이다.
PageRequest는 of메서드를 통해 PageRequest개체를 생성한다.
EX) 페이징 쿼리 메서드를 호출하는 방법
Page<Product> productPage =
productRepository.findByName("펜",PageRequest.of(0,2));
getContent() : Page객체 데이터 출력
EX) Page객체의 데이터 출력
Page<Product> productPage =
productRepository.findByName("펜",PageRequest.of(0,2));
System.out.println(productPage.getContent());
@Query어노테이션을 사용해 직접 JPQL을 작성할 수 있다.
EX) @Query어노테이션과 @Param어노테이션을 사용한 메서드
@Query("SELECT p FROM Product p WHERE p.name = :name")
List<Product> findByNameParam(@Param("name") String name);
@Query 를 사용하면 Entity타입이 아니라 원하는 칼럼의 값만 추출할 수 있다.
SELECT에서 가져오고자 하는 칼럼을 지정하면 된다.
이때 메서드에서는 Object배열의 리스트 형태로 리턴 타입을 지정해야 한다.
@Query("SELECT p.name, p.price, p.stock FROM Product p WHERE p.name = :name")
List<Object[]> findByNameParam2(@Param("name") String name);