[Spring Data JPA Tutorial] 3. Spring Data JPA Query Methods 명명규칙

2021. 2. 18. 19:59Spring/Spring Data JPA Tutorial

반응형
  1. Subject Part
    1. find...By
    2. exists...By
    3. counts...By
    4. ...First<number>...
  2. Predicate Part - 1) Predicate Keyword
    1. [Is]
    2. [Is]Not
    3. [Is]Null, [Is]NotNull
    4. [Is]Empty, [Is]NotEmpty
    5. [Is]True, [Is]False
    6. And
    7. Or
    8. [Is]GreaterThan, [Is]LessThan, [Is]Between
    9. [Is]Like, [Is]Containing, [Is]StartingWith, [Is]EndingWith
  3. Predicate Part - 2) Predicate Modifier Keyword

Query Methods

이전시간에 소개했던 Query Methods를 정의하는 방법에 대해 상세히 알아보도록 합시다.

Query Method의 이름은 Subject Part과 Predicate Part로 구분됩니다.
첫번째 By 까지를 Subject Part, 첫번째 By 이후의 부분을 Predicate Part로 칭합니다.

1. Subject Part

찾고자하는 주제에 해당됩니다.
별도의 설정이 없다면 모든 컬럼을 조회하고, Limit나 Distinct 등의 설정이 가능합니다.

1.1. find...By

Entity를 조회할 때 사용하는 키워드입니다. find 대신 read, get, query, search, stream 을 사용할 수도 있으나 find...By로 가장 많이 사용합니다.

단건 조회나, 복수(Collections 또는 Page형태) 조회할 수 있습니다.

Optional<User> findById(Long id);
List<User> findAllById(List<Long> ids);

1.2. exists...By

조회 유무를 boolean 타입으로 반환합니다.

boolean existsById(Long id);

1.3. counts...By

검색 결과에 따른 총 record 수를 반환합니다.

long countByActive(boolean active);

1.4. ...First<number>...

조회할 query 결과값 수를 제한하는 Subject Part 키워드는 First, Top 입니다.
둘은 동일하게 작동되는 키워드이며, find..By 부분의 가운데에 위치합니다.

단순하게 맨 첫번째 쿼리를 조회하고자 할때에는 아래와 같이 별도의 인자 설정없이 조회가 가능합니다.

Optional<User> findFirstByOrderByIdDesc();
Optional<User> findTopByOrderByNameAsc();

다만, 조회하고자하는 쿼리 수가 1개보다 크거나 페이징처리가 필요할 때에는 Pageable 또는 Sort와 같은 인자를 설정해줘야 합니다.

Page<User> findFirst5ByStatus(String status, Pageable pageable);
Slice<User> findTop10ByType(String type, Pageable pageable);

List<User> findFirst10BySex(String sex, Sort sort);
List<User> findTop3ByStatus(String status, Pageable pageable);

참고로 Pageable과 Sort는 Null을 허용하지 않기 때문에, 해당 인자에 null이 들어갈 경우 에러를 발생시킵니다.
만일 Sort나 Pageable을 사용하고 싶지않을 경우에는 Sort.unsorted(), Pageable.unpaged()를 사용하면 됩니다.


1.5. Distinct 추후 정리


2. Predicate Part - 1) Predicate keyword

Predicate Part는 첫번째 By 이후 부분으로, 검색 및 정렬 조건을 작성합니다.
그 중, 조회 쿼리에 대한 검색 조건을 설정하는 Predicate keyword에 대해 먼저 살펴보도록 하겠습니다.

검색을 하기 위해 약속된 키워드들이 정의되어있고, 그 키워드 중에는 동일하게 작동되는 키워드들이 존재합니다.

동일하게 동작하는 키워드들이 중복적으로 존재하는데, 간단하게 2가지 규칙이 있다고 보면 이해하기 쉽습니다.

  1. Is는 컬럼 검색조건 키워드의 Prefix에 붙일 수 있으며, 생략가능합니다.
  2. -ings로 교체가능(s를 붙일 때에는 Is 키워드는 쓰지 않습니다)

자세한 사항은 예제 코드를 보면서 참고하시길 바랍니다.

2.1. [Is]

기본 일치 검색
키워드를 생략해도 동일하게 작동되며, 동일한 기능의 키워드로 Equals가 있습니다.

  •   SELECT u FROM users u WHERE email = ?1;
    
    •   Optional<User> findByEmail(String email);
        Optional<User> findByEmailIs(String email);
        Optional<User> findByEmailEquals(String email);
      

위의 3가지 메서드는 동일하게 작동되며, 통상적으로 키워드를 생략하여 사용합니다.


2.2. [Is]Not

컬럼 단순 불일치 조건

  •   SELECT u FROM users u WHERE email <> ?1;
    
    •   Optional<User> findByEmailNot(String email);
        Optional<User> findByEmailIsNot(String email);
      

2.3. [Is]Null, [Is]NotNull

컬럼값이 NULL인 레코드 검색하는 Null과 NULL이 아닌 레코드를 검색하는 NotNull.

  •   SELECT u FROM users u WHERE u.updatedAt IS NULL;
    
    •   Optional<User> findByUpdatedAtNull();
        Optional<User> findByUpdatedAtIsNull();
      
  •   SELECT u FROM users u WHERE u.updatedAt IS NOT NULL;
    
    •   Optional<User> findByUpdatedAtNotNull();
        Optional<User> findByUpdatedAtIsNotNull();
      

2.4. [Is]Empty, [Is]NotEmpty

컬럼값이 NULL이거나 빈문자열인 레코드 검색하는 Empty 키워드입니다.
반대키워드는 NotEmpty 입니다.

  •   SELECT u FROM users u WHERE u.name IS NULL OR u.name = '';
    
    •   Optional<User> findByNameEmpty();
      

2.5. [Is]True, [Is]False

boolean 타입의 컬럼의 True/False를 검색합니다.

  •   SELECT u FROM users u WHERE u.active = true;
    
    •   List<User> findByActiveTrue();
      
  •   SELECT u FROM users u WHERE u.active = false;
    
    •   List<User> findByActiveFalse();
      

2.6. And

조건을 and 조건으로 엮고 싶을때 사용합니다.
키워드: And

  •   SELECT u FROM users u WHERE u.type = ?1 AND u.active = ?2;
    
    •   List<User> findByTypeAndActive(String type, String active);
      

2.7. Or

조건을 or 조건으로 엮고 싶을때 사용합니다.
키워드: Or

  •   SELECT u FROM users u WHERE u.type = ?1 OR u.active = ?2;
    
    •   List<User> findByTypeOrActive(String type, String active);
      

2.8. [Is]GreaterThan, [Is]LessThan, [Is]Between

비교 연산을 지원하는 numeric, datetime 데이터타입의 컬럼에 설정할 수 있는 조건 연산입니다.
GreaterThan와 LessThan 키워드 뒤에 Equal를 붙여서 크거나 같은, 작거나 같은 조건도 설정할 수 있습니다.

  •   SELECT u FROM users u WHERE u.age < ?1;
    
    •   List<User> findByAgeLessThan(int age);
      
  •   SELECT u FROM users u WHERE u.age >= ?1;
    
    •   List<User> findByAgeGreaterThanEqual(int age);
      
  •   SELECT u FROM users u WHERE u.age BETWEEN ?1 AND ?2;
    
    •   List<User> findByAgeBetween(int age1, int age2);
      
    •   List<User> findByAgeGreaterThanEqualAndAgeLessThanEqual(int age1, int age2);
      

2.9. [Is]Like, [Is]Containing, [Is]StartingWith, [Is]EndingWith

컬럼의 일부분이 일치하는 레코드를 검색

sql 표준문법에서 character 수와 상관없이 문자열 포함여부를 검색할때 %를 이용합니다.
Containing(= Contains), StartingWith(= StartsWith), EndingWith(= EndsWith)에서는 편의상 검색할 문자열에 %를 자동으로 붙여줍니다.

Containing에는 양쪽에, StartingWith는 뒤에. EndingWith는 앞에 붙여서 기능을 동작합니다.


Like 키워드의 경우, 인자에 %_를 명시적으로 설정해야하니 이 부분을 주의해주세요.

_를 이용할 것이 아니라면 편의를 위해 Containing, StartingWith, EndingWith 키워드를 사용하는것을 권장합니다.


  •   SELECT u FROM users u WHERE u.email like ?1;
    
    •   List<User> findByEmailLike(String email);
        List<User> findByEmailIsLike(String email);
      
  •   SELECT u FROM users u WHERE u.email like %?1%;
    
    •   List<User> findByEmailContains(String email);
        List<User> findByEmailContaining(String email);
        List<User> findByEmailIsContaining(String email);
      
  •   SELECT u FROM users u WHERE u.email like ?1%;
    
    •   List<User> findByEmailStartsWith(String email);
        List<User> findByEmailStartingWith(String email);
        List<User> findByEmailIsStartingWith(String email);
      
  •   SELECT u FROM users u WHERE u.email like %?1;
    
    •   List<User> findByEmailEndsWith(String email);
        List<User> findByEmailEndingWith(String email);
        List<User> findByEmailIsEndingWith(String email);
      

3. Predicate Part - 2) Predicate Modifier Keyword

3.1. IgnoreCase

특정 컬럼의 대소문자를 구분하지 않고 검색합니다.

List<User> findByDeviceOsIgnoreCase(String deviceOs);
List<User> findByDeviceOsIgnoringCase(String deviceOs);

3.2. AllIgnoreCase

모든 컬럼의 대소문자를 구분하지 않고 검색합니다.

List<User> findByNameOrEmailAllIgnoreCase(String name, String email);
List<User> findByNameOrEmailAllIgnoringCase(String name, String email);

3.2. OrderBy...

정렬할 요소를 설정합니다.
정렬방식을 컬럼 뒤에 붙일 수 있고, 생략할 경우 오름차순으로 설정됩니다.

오름차순(Asc), 내림차순(Desc)

List<User> findByActiveOrderByIdDesc(boolean active);
List<User> findByActiveOrderByTypeAscNameAsc(String type, String name);

++ Reference

  1. https://docs.spring.io/spring-data/jpa/docs/2.4.3/reference/html/#jpa.query-methods
  2. https://docs.spring.io/spring-data/jpa/docs/2.4.3/reference/html/#repository-query-keywords
728x90
반응형