<목차>
1. JPQL 쿼리 메서드
2. Subject / Predicate Keywords
3. Sort / Paging
[JPQL 쿼리 메서드]
JPQL 은, JPA Query Language 의 약자로, JPA에서 사용할 수 있는 쿼리를 의미한다.
JPQL 은 Entity 객체를 대상으로 수행하는 쿼리이기 때문에, 매핑된 엔티티의 이름과 필드의 이름을 사용한다.
Repository 는 JpaRepository 를 상속받는 것 만으로도 다양한 기본 쿼리 메서드를 사용할 수 있다.
하지만, 기본 메서드의 경우 엔티티의 Id (PK, 식별자) 기반으로 제공되기 때문에, 결국 별도의 메서드를 정의하여 사용하는 경우가 많으며, 이를 '쿼리 메서드' 라고 한다.
쿼리 메서드는, 크게 동작을 결정하는 주제(Subject) 와 서술어(Predicate)로 구분한다.
- Subject
- find ~ By / exists ~ By 와 같은 키워드로 주제를 정한다.
- Predicate
- By 를 기점으로 이후 부분이 서술어이며, 검색 및 정렬 조건을 지정한다.
- 엔티티의 속성(필드)로 정의할 수 있으며, And / Or 을 사용하여 조건을 확장할 수 있다.
ex) findByNameAndAge(String name, long age)
[Subject Keywords]
쿼리 메서드의 주제 영역에 사용할 수 있는 주요 키워드
- 조회 쿼리 메서드 키워드
- 조건에 맞는 데이터를 조회하는 키워드로, Collection / Stream 의 하위 타입을 리턴 타입으로 설정할 수 있다.
- find ~ By : 가장 일반적으로 사용되는 키워드로, 조건에 맞는 데이터를 조회한다.
동일한 역할을 하는 키워드로, read ~ By / get ~ By / query ~ By / search ~ By / stream ~ By 등이 있다.
// 조회 키워드를 활용한 쿼리 메서드
Optional<Product> findByNumber(Long number);
List<Product> findAllByName(String name);
Product queryByNumber(Long number);
- exists ~ By : 특정 데이터가 존재하는지 확인하는 키워드로, boolean 타입으로 리턴한다.
boolean existsByNumber(Long number);
- count ~ By : 쿼리를 수행한 후, 결과로 나온 Row 개수를 리턴한다.
long countByName(String name);
- delete ~ By / remove ~ By : 삭제 쿼리를 수행한 후, 삭제 횟수를 리턴한다. (void 가능)
long deleteByNumber(long number); // 삭제된 Row 수 리턴
void removeByNumber(long number); // void 로도 처리 가능
- ~ First{number} ~ / ~ Top{number} ~ : 쿼리로 조회된 결과값의 개수를 제한하는 키워드로, 흔히 알고 있는 limit / top 등의 역할을 수행한다.
List<Product> findFirst5ByName(String name);
List<Product> findTop5ByName(String name);
[Predicate Keyword]
쿼리 메서드의 서술어 영역에 사용할 수 있는 주요 키워드
- Is / Equals : 값의 일치를 조건으로 사용하는 조건자 키워드
생략 가능하다.
// Is, Equals > 일치하는 데이터를 찾는다.
// findByNumber() 와 동일하게 동작한다
Product findByNumberIs(Long number);
Product findByNumberEquals(Long number);
- (Is)Not : 값의 불일치를 조건으로 사용하는 조건자 키워드
// (Is)Not > 불일치하는 데이터를 찾는다.
Product findByNumberIsNot(Long number);
Product findByNumberNot(Long number);
- (Is)Null / NotNull : Null 체크하는 조건자 키워드
SQL 에서의 IS NULL / IS NOT NULL 과 동일
// (Is)Null, (Is)NotNull
List<Product> findByUpdatedAtNull();
List<Product> findByUpdatedAtIsNull();
List<Product> findByUpdatedAtNotNull();
List<Product> findByUpdatedAtIsNotNull();
- (Is)True / False : boolean 타입으로 지정된 컬럼 값을 확인하는 키워드
// (Is)True, (Is)False
Product findByIsActiveTrue();
Product findByIsActiveIsTrue();
Product findByIsActiveFalse();
Product findByIsActiveIsFalse();
- And / Or : 여러 조건을 연결할 때 사용
// And, Or > 조건을 묶을 때 사용
Product findByNumberAndName(Long number, String nme);
Product findByNumberOrName(Long number, String name);
- (Is)GreaterThan / LessThan / Between : 숫자 또는 datetime 타입의 컬럼을 대상으로 비교 연산에 사용할 수 있는 키워드
- 초과 : GreaterThan
- 이상 : GreaterThanEqual
- 미만 : LessThan
- 이하 : LessThanEqual
// (Is)GreaterThan, (Is)LessThan, (Is)Between + Equal
// GreaterThan
List<Product> findByPriceIsGreaterThan(Long price); // Price 초과
List<Product> findByPriceGreaterThan(Long price); // Price 초과
List<Product> findByPriceGreaterThanEqual(Long Price); // Price 이상
// LessThan
List<Product> findByPriceIsLessThan(Long price); // Price 미만
List<Product> findByPriceLessThan(Long price); // Price 미만
List<Product> findByPriceLessThanEqual(Long Price); // Price 이하
// Between
List<Product> findByPriceBetween(Long lowPrice, Long highPrice);
List<Product> findByPriceIsBetween(Long lowPrice, Long highPrice);
- (Is)StartingWith / EndingWith / Containing / Like
startsWith / EndsWith / Contains- SQL 에서의 LIKE 역할을 하는 키워드이다.
- StartingWith(StartsWith) : 문자열 앞에 '%' 가 배치된다.
- EndingWith(EndsWith) : 문자열 뒤에 '%' 가 배치된다.
- Contining(Contains) : 문자열 앞 뒤에 '%' 가 배치된다.
- Like : '%' 를 원하는 위치에 배치시킨 문자열 자체가 파라미터로 전달되어야 한다.
// (Is)StartsWith / StartingWith, (Is)EndsWith / EndingWith, (Is)Contains / Containing, (Is)Like
// StartsWith / StartingWith
List<Product> findByNameStartsWith(String name);
List<Product> findByNameStartingWith(String name);
List<Product> findByNameIsStartingWith(String name);
// EndsWith / EndingWith
List<Product> findByNameEndsWith(String name);
List<Product> findByNameEndingWith(String name);
List<Product> findByNameIsEndingWith(String name);
// Contains / Containing
List<Product> findByNameContains(String name);
List<Product> findByNameContaining(String name);
List<Product> findByNameIsContaining(String name);
// Like > 파라미터의 원하는 위치에 '%' 를 입력하여 호출해야 함
List<Product> findByNameLike(String name);
List<Product> findByNameIsLike(String name);
- OrderBy : 일반적인 쿼리문과 동일하게 OrderBy 구문을 사용한다.
기본 쿼리메서드의 뒷부분에 OrderBy ~ Asc / Desc 를 입력해주면 되며, 둘 이상의 정렬 조건을 부여해야 한다면 우선순위대로 나열해주면 된다.(And 와 같은 키워드는 불필요)
// 정렬
List<Product> findByNameOrderByNumberAsc(String name);
List<Product> findByNameOrderByNumberDesc(String name);
List<Product> findByNameOrderByPriceAscStockDesc(String name);
// 정렬 컬럼 간 And 연결하지 않고 나열
List<Product> findByName(String name, Sort sort);
[Sort / Paging]
- Sort
정렬 시, OrderBy 키워드를 통해 정렬하는 방법은, 대상 필드의 수가 많아지면 메서드명이 길어지며 가독성이 떨어지게 될 수 있기 때문에, Sort 객체를 사용하여 정렬하는 방법도 알아보자.
1. Sort 객체를 파리미터로 받는 메서드 정의
List<Product> findByName(String name, Sort sort);
2. 메서드 호출 시, Sort.by() 사용하여 정렬 조건 설정
List<Product> productList = productRepository.findByName("펜", Sort.by(Order.asc("price"), Order.desc("stock")));
- Paging
JPA에서는 페이징 처리를 위해 Page와 Pageabl을 사용한다.
페이징을 위한 쿼리 메서드는, 리턴 타입으로 Page을 사용하고, 파라미터는 Pageable 타입의 객체를 정의한다.
1. 페이징 처리를 위한 쿼리 메서드 정의
Page<Product> findByName(String name, Pageable pageable);
2. 메서드 호출 시, PageRequest.of() 사용하여 페이징 조건 설정
Page<Product> productPage = productRepository.findByName("펜", PageRequest.of(0, 2));
- PageRequest는 Pageable 의 구현체
- PageRequest.of()
- of(int page, int size) -> (페이지 번호, 페이지 당 데이터 수)
- of(int page, int size, Sort sort) -> (페이지 번호, 페이지 당 데이터 수, 정렬 조건)
관련 소스
[Github]
spring-boot-study/advjpa at main · jh4dev/spring-boot-study
스프링 부트 스터디. Contribute to jh4dev/spring-boot-study development by creating an account on GitHub.
github.com
[참고 도서]

<스프링 부트 핵심 가이드>
저자 : 장정우
출판사 : 위키북스
'Spring & Spring boot' 카테고리의 다른 글
[Spring Boot] JPA - 7. QueryDSL 사용 방법 (0) | 2024.08.11 |
---|---|
[Spring Boot] JPA - 6. QueryDSL 설정 (0) | 2024.08.11 |
[Springboot] 테스트 코드 - 8 - Repository Unit Test 리포지토리 단위 테스트 (0) | 2024.08.08 |
[Springboot] 테스트 코드 - 7 - Service Unit Test 서비스 단위 테스트 (0) | 2024.08.07 |
[Springboot] 테스트 코드 - 6 - Controller Unit Test 컨트롤러 단위 테스트 (0) | 2024.08.07 |