Book/스프링부트 핵심가이드

Spring Data JPA 쿼리 메서드 개념과 사용 방법

블로그 주인장 2023. 11. 8.

Spring Data JPA 활용

리포지토리 예제를 작성하고, 리포지토리 활용법을 테스트 코드를 통해 알아보겠습니다.


 

JPQL


  1. JPQL은 JPA Query Language의 줄임말로써, JPA에서 사용할 수 있는 쿼리를 의미한다.
  2. JPQL의 문법은 SQL과 매우 비슷해서 데이터베이스 쿼리에 익숙한 사람들은 쉽게 사용할 수 있다.
  3. SQL  vs JPQL
    • SQL에서는 테이블이나 컬럼의 이름을 사용한다.
    • JPQL은 엔티티 객체를 대상으로 수행하는 쿼리이기에 매핑된 엔티티의 이름과 필드의 이름을 사용한다는 것이다.

 

쿼리 메서드


기본 메서드는 식별자 기반으로 생성되기에, 별도의 메서드를 정의해서 사용하는 경우가 많다.

이 때 간단한 쿼리문을 작성하기 위해 사용되는 것이 쿼리 메서드 이다.

 

쿼리 메서드 생성

  • 쿼리 메서드는 크게 동작을 결정하는 주제(Subject)와 서술어(Predicate)로 구분된다.
  • "find···By", "exist···By" 와 같은 키워드로 쿼리의 주제를 정한다.
  • 'By' 는 서술어의 시작을 나타내는 구분자 역할을 한다.
    • 서술어 부분은 검색 및 정렬 조건을 지정하는 영역이다.
    • 기본적으로 엔티티의 속성을 정의할 수 있고, AND or OR를 이용하여 조건을 확장하는 것도 가능하다.

 

쿼리 메서드의 주제 키워드

  1. find···By
  2. read···By
  3. get···By
  4. query···By
  5. search···By
  6. stream···By
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    Optional<Product> findByNumber(Long number);
    
    List<Product> findAllByName(String name);
    
    Product queryByNumber(Long number);
}

 

1️⃣ exist···By

  • 특정 데이터가 존재하는 지 확인하는 키워드이다.
  • 리턴 타입은 boolean 타입을 사용한다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    boolean existByNumber(Long number);
}

 

2️⃣ count···By

  • 조회 쿼리를 수행한 후 쿼리 결과로 나온 레코드 개수를 리턴한다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    Long countByName(String name);
}

 

3️⃣ delete···By, remove···By

  • 삭제 쿼리를 수행한다.
  • 리턴 타입이 없거나 삭제한 횟수를 리턴한다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {

    void deleteByNumber(Long number);
    
    long removeByName(String name);
}

 

4️⃣ ···First<number> ··· , ···Top<number> ···

  • 쿼리를 통해 조회된 결과값의 갯수를 제한하는 키워드이다.
  • 두 키워드는 동일한 동작을 수행하며, 주제와 By 사이에 위치한다.
  • 일반적으로 한 번의 동작으로 여러 건을 조회할 때 사용되며, 단 건으로 조회하기 위해서는 <...> 를 생략하면 된다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {

    List<Product> findFirst5ByName(String name);
    
    List<Product> findTop10ByName(String name);
}

 

쿼리 메서드의 조건자 키워드

1️⃣ Is

  • 값의 일치를 조건으로 사용하는 조건자 키워드이다.
  • 생략되는 경우가 많으며 Equals와 동일한 기능을 수행한다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {

    Product findByNumberIs(Long number);
    
    Product findByNumberEquals(Long number);
}

 

2️⃣ (Is)Not

  • 값의 불일치를 조건으로 사용하는 조건자 키워드이다.
  • Is는 생략하고 Not 키워드만 사용할 수도 있다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {

    Product findByNumberIsNot(Long number);
    
    Product findByNumberNot(Long number);
}

 

3️⃣ (Is)Null, (Is)NotNull

  • 값이 null 인지 검사하는 조건자 키워드이다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findByUpdatedAtNull();
    List<Product> findByUpdatedAtIsNull();
    List<Product> findByUpdatedAtNotNull();
    List<Product> findByUpdatedAtIsNotNull();
}

 

4️⃣ (Is)True, (Is)False

  • boolean 타입으로 지정된 칼럼값을 확인하는 키워드이다.
  • 엔티티에 boolean 타입을 사용하는 칼럼이 없는 경우 실제 코드에 반영하면 에러만 발생하기에, 참고만 해야한다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    Product findByActiveTrue();
    Product findByActiveIsTrue();
    Product findByActiveFalse();
    Product findByActiveIsFalse(); 
}

 

5️⃣ And, Or

  • 여러 조건을 묶을 때 사용한다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    Product findByNumberAndName(Long number, String name);
    Product findByNumberOrName(Long number, String name);
}

 

6️⃣ (Is)GreaterThan, (Is)LessThan, (Is)Between

  • 숫자나 datetime 컬럼을 대상으로 한 비교 연산에 사용할 수 있는 조건자 키워드이다.
  • GreaterThan, LessThan 키워드는 비교 대상에 대한 초과/미만의 개념으로 비교 연산을 수행한다.
  • 경계값을 포함하려면 Equal 키워드를 추가하면 된다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    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);    
}

 

7️⃣ (Is)StartingWith(==StartsWith), (Is)EndingWIth(==EndWith), (Is)Containing(==Contains), (Is)Like

  • 컬럼 값에서 일부 일치 여부를 확인하는 조건자 키워드이다.
  • SQL 쿼리문에서 값의 일부를 포함하는 값을 추출할 때 사용하는 '%' 키워드와 동일한 역할을 하는 키워드이다.
    • 자동으로 생성되는 SQL문을 보면 Containing 키워드는 문자열의 양 끝에 '%' 가 배치된다.
    • StartingWith 키워드는 문자열의 앞에 '%' 가 배치된다.
    • EndingWith 키워드는 문자열의 끝에 '%' 가 배치된다.
    • Like 키워드는 코드 수준에서 메서드를 호출하면서 전달하는 값에 '%'를 명시적으로 입력해야한다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    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);         
}
반응형

댓글