
: 스프링 부트를 활용한 애플리케이션 개발 실무
📝 목차
8장. Spring Data JPA 활용
8-1. 프로젝트 생성
8-2. JPQL
8-3. 쿼리 메서드 살펴보기
- 쿼리 메서드의 생성
- 쿼리 메서드의 주제 키워드
- 쿼리 메서드의 조건자 키워드
: JPA에서 사용할 수 있는 쿼리
JPQL의 문법은 SQL과 매우 비슷하며, SQL을 기반으로 한 언어다.
JPQL과 SQL과의 차이점
: JPQL은 데이터베이스의 테이블이 아니라, JPA에서 매핑한 엔티티 객체를 대상으로 쿼리를 수행한다.
➙ SQL에서 사용하는 테이블 이름, 칼럼 이름 대신 JPQL에서는 매핑된 엔티티 클래스의 이름과 그 속성(필드) 이름을 사용하여 쿼리를 작성!

: 리포지토리(Repository)는 JpaRepository를 상속 ➙ 다양한 CRUD 메서드를 제공
기본 메서드들은 식별자 기반으로 생성 ➙ 결국 별도의 메서드를 정의해 사용
이때, 간단한 쿼리문을 작성하기 위해 사용되는 것 = 쿼리 메서드
쿼리 메서드 = 동작을 결정하는 주제 (Subject) + 서술어 (Predicate)
[Subject]
[Predicate]
✅ 리포지토리의 쿼리 메서드 생성 예시
// (리턴 타입) + {주제 + 서술어(속성)} 구조의 메서드
List<Person> findByLastnameAndEmail (String lastName, String email);
서술어에 들어가는 엔티티의 속성 식(Expression)은 ➙ LastnameAndEmail
위의 예시와 같이 엔티티에서 관리하고 있는 속성(필드)만 참조할 수 있다.
'...'으로 표시한 영역에는 도메인(엔티티)을 표현 할 수 있다.
리포지토리에서 이미 도메인을 설정한 후 메서드를 사용 ➙ 생략 가능
✅ 조회하는 기능을 수행하는 키워드
➡️ 리턴 타입 : Collection이나 Stream에 속한 하위 타입 설정
- find...By
- read・・・By
- get・・・By
- query・・・By
- search・・・By
- stream・・・By
// find...By
Optional<Product> findByNumber(Long number);
List<Product> findAllByName(String name);
Product queryByNumber(Long number);
✅ 특정 데이터가 존재하는지 확인하는 키워드
➡️ 리턴 타입 : boolean 타입 사용
- exists...By
//exists...By
boolean existsByNumber(long number);
✅ 조회 쿼리를 수행 ➡️ 쿼리 결과로 나온 레코드의 개수를 리턴
- count...By
//count...By
long countByName(String name);
✅ 삭제 쿼리 수행 ➡️ 리턴 타입이 없거나, 삭제한 횟수를 리턴
- delete...By
- remove...By
//delete...By, remove...By
void deleteByNumber(long number);
long removeByName(String name);
✅ 쿼리를 통해 조회된 결괏값의 개수를 제한하는 키워드
두 키워드는 동일한 동작을 수행
- ...First...
- ...Top...
주제와 By 사이에 위치
한번의 동작으로 여러 건을 조회할 때 사용되며,
단 건으로 조회하기 위해서는 <number> 를 생략하면 된다.
//...First<number>..., ...Top<number>...
List<Product> findFirst5ByName(String name);
List<Product> findTop10ByName(String name);
: JPQL의 서술어 부분에서 사용할 수 있는 조건자 키워드
✅ 값의 일치를 조건으로 사용하는 조건자 키워드
: 생략되는 경우가 많고, Equals와 동일한 기능을 수행
- Is
// findByNumber 메서드와 동일하게 동작
Product findByNumberIs(Long number);
Product findAllByNumberIs(Long number);
✅ 값의 불일치를 조건으로 사용하는 조건자 키워드
: Is는 생략하고 Not 키워드만 사용할 수도 있다.
- (Is) Not
//(is)Not
Product findByNumberIsNot(Long number);
Product findByNumberNot(Long number);
✅ 값이 null인지 검사하는 조건자 키워드
- (Is)Null
- (Is)NotNull
//(Is)Null, (Is)NotNull
List<Product> findByUpdatedAtNull();
List<Product> findByUpdatedAtIsNull();
List<Product> findByUpdatedAtNotNull();
List<Product> findByUpdatedAtIsNotNull();
✅ boolean 타입으로 지정된 컬럼값을 확인하는 키워드
: 엔티티에 boolean 타입을 사용하는 칼럼이 없으면 에러가 발생
- (Is)True
- (Is)False
//(Is)True, (Is)False
Product findByisActiveTrue();
Product findByisActiveIsTrue();
Product findByisActiveFalse();
Product findByisActiveIsFalse();
✅ 여러 조건을 묶을 때 사용
- And
- Or
//And, Or
Product findByNumberAndName(Long number, String name);
Product findByNumberOrName(Long number, String name);
✅ 비교연산에 사용할 수 있는 조건자 키워드 ➡️ 숫자, datetime 칼럼만!
: 경계값을 포함하려면 Equal 키워드 추가
- (Is)GreaterThan - 초과
- (Is)LessThan - 미만
- (Is)Between
// (Is)GreaterThan, (Is)LessThan, (Is)Between
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)StartingWith(==StartsWith)
- (Is)EndingWith(==EndsWith)
- (Is)Containing(==Contains)
- (Is)Like
⬇️
SQL 쿼리문에서 값의 일부를 포함하는 값을 추출할 때 사용하는 % 키워드와 동일한 역할을 하는 키워드
여기서 별도로 고려해야하는 Like키워드
Like키워드는 코드 수준에서 메서드를 호출하면서 전달하는 값에 %를 명시적으로 입력해야 한다.
// (Is)StartingWith(==StartsWith),
// (Is)EndingWith(==EndsWith)
// (Is)Containing(==Contains)
// (Is)Like
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);