be_better

[Springboot] Spring Data JPA 활용 - JPQL 본문

Springboot/이론

[Springboot] Spring Data JPA 활용 - JPQL

NiceTry 2023. 11. 10. 16:02

목차

    JPQL

    JPQL은 JPA Query Language의 줄임말로 JPA에서 사용할 수 있는 쿼리를 의미한다. SQL과의 차이점은 SQL에서는 테이블이나 칼럼의 이름을 사용하는 것과 달리 JPQL은 엔티티 객체를 대상으로 수행하는 쿼리이기 때문에 매핑된 엔티티의 이름과 필드의 이름을 사용한다는 것이다.

     

    쿼리 메서드 살펴보기

    리포지토리는 JpaRepository를 상속받는 것만으로도 다양한 CRUD 메서드를 제공한다. 하지만 이러한 기본 메서드들은 식별자 기반으로 생성되기 때문에 결국 별도의 메서드를 정의해서 사용하는 경우가 많다. 이때 간단한 쿼리문을 작성하기 위해 사용되는 것이 쿼리 메서드이다.

     

    쿼리 메서드의 생성

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

     

    // (리턴타입) + {주제 + 서술어(속성)} 구조의 메서드
    List<Person> findByLastnameAndEmail(String lastName, String email);

    서술어에 들어가는 엔티티의 속성 식(Expression)은 위의 예시와 같이 엔티티에서 관리하고 있는 속성(필드)만 참조할 수 있다.

     

    쿼리 메서드의 주제 키워드

    주제 부분에 사용할 수 있는 주요 키워드는 다음과 같다

    • find...By
    • read...By
    • get...By
    • query...By
    • search...By
    • stream...By

    리턴 타입으로는 Collection이나 Stream에 속한 하위 타입을 설정할 수 있다.

    // find ... By
    Optional<Product> findByNumber(Long number);
    List<Product> findAllByName(String name);
    Product queryByNumber(Long number);

     

    exists...By

    특정 데이터가 존재하는지 확인하는 키워드. 리턴 타입으로는 boolean 타입을 사용한다.

    // 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<number>..., ...Top<number>...

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

    // ...First<number>..., ...Top<number>...
    List<Product> findFirst5ByName(String name);
    List<Product> findTop10ByName(String name);

     

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

    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, (Is)NotNull

    값이 null인지 검사하는 조건자 키워드

    // (Is)Null
    List<Product> findByUpdatedAtNull();
    
    // IsNull
    List<Product> findByUpdatedAtIsNull();
    
    // (Is)NotNull
    List<Product> findByUpdatedAtNotNull();
    
    // IsNotNull
    List<Product> findByUpdatedAtIsNotNull();

     

    (Is)True, (Is)False

    boolean 타입으로 지정된 칼럼값을 확인하는 키워드.

    // True
    Product findByisActiveTrue();
    Product findByisActiveisTrue();
    
    // False
    Product findByisActiveFalse();
    Product findByisActiveisFalse();

     

    And, Or

    여러 조건을 묶을 때 사용한다.

    Product findByNumberAndName(Long number, String name);
    Product findByNumberOrName(Long number, String name);

     

    (Is)GreaterThan, (Is)LessThan, (Is)Between

    숫자나 datetime 컬럼을 대상으로 한 비교 연산에 사용할 수 있는 조건자 키워드. GreaterThan, LessThan 키워드는 비교 대상에 대한 초과/미만의 개념으로 비교 연산을 수행하고, 경계값을 포함하려면 Equal 키워드를 추가하면 된다.

    // GreaterThan
    List<Product> findByPriceIsGreaterThan(Long price);
    List<Product> findByPriceGreaterThan(Long price);
    List<Product> findByPriceIsGreaterThanEqual(Long price);
    
    // LessThan
    List<Product> findByPriceIsLessThan(Long price);
    List<Product> findByPriceLessThan(Long price);
    List<Product> findByPriceLessThanEqual(Long price);
    
    // Between
    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 쿼리문에서 '%' 키워드와 동일한 역할을 하는 키워드이다. Containing 키워드는 문자열의 양 끝, StartingWith 키워드는 문자열의 앞, EndingWith 키워드는 문자열의 끝에 '%'가 배치된다.

    // Like, IsLike
    List<Product> findByNameLike(String name);
    List<Product> findByNameIsLike(String name);
    
    // Contains, Containing
    List<Product> findByNameContains(String name);
    List<Product> findByNameContaining(String name);
    List<Product> findByNameIsContaining(String name);
    
    // 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);