본문 바로가기
[IT] Spring Boot (JAVA)/[JPA] Spring Data JPA

[JPA] Spring Data JPA - Query Methods (쿼리 메서드)

by 오리엔탈킴 2022. 5. 10.

안녕하세요, Spring Data JPA의 쿼리를 생성하는 기능 중 한 개인 메서드명을 규칙에 맞게 작성을 하면, 자동으로 쿼리가 생성되는 Query Methods (쿼리 메서드) 기능에 대해서 알아보겠습니다. 아주 복잡한 Entity나 Join 상황에서는 활용이 힘들겠지만, 간단하게 데이터를 불러오거나 저장하는 상황에서는 아주 유용하게 활용이 가능할 것 같습니다.

쿼리 메서드 샘플 예제

User Entity

아래와 같이 간략히 User Entity를 작성합니다.

쿼리 메서드를 사용시 변수명을 기준으로 작성이 되는데, 첫 글자가 대문자는 불가능하고 중간에 "_" 언더바 같은 기호도 인식이 불가능합니다. DB 테이블에 칼럼명을 이런 규칙을 어기면서 생성해야 하는 경우에는 아래와 같이 @Column(name = "First_Name") 어노테이션을 활용합니다.

@Entity
@Getter
@Setter
public class User {
    
    @Id
    private long userId;

    @Column(name = "FirstName")
    private String firstname;

    @Column(name = "Last_name")
    private String lastname;

    private int age;

    private LocalDateTime startDate;

    private boolean active;

}

 

User Repository

메소드 쿼리 예시를 억지로(?) 작성을 해보면 아래와 같습니다. 대문자로 키워드 분리하여 자동으로 인식하니 대소문자에 유의하여 작성을 해야 합니다. 또한 매개변수명은 어떤 것을 해도 순서대로 입력이 들어오지만, 명확한 코드를 위해 칼럼명으로 작성을 합니다.

@Repository
public interface UserRepository extends JpaRepository< User, Long > {

    List<User> findFirst5ByLastnameAndFirstnameOrderByUserIdDesc(String lastName, String firstName);

    Boolean existsByStartDateLessThanEqual(LocalDateTime startDate);

    long countByFirstnameIgnoreCaseLike(String firstName);
    
}

 

  • 첫 번째 메서드는 lastname과 firstname이 입력받은 값과 일치하는 User들을 userId 역순으로 정렬을 하여 5개 데이터만 가져옵니다.
userRepository.findFirst5ByLastnameAndFirstnameOrderByUserIdDesc("ori", "kim");

실제 수행된 쿼리를 보면 아래와 같습니다.

select *
from user
where last_name=?
and first_name=?
order by user_id desc limit 5

 

  • 두번째 메서드는 입력받은 날짜보다 startDate가 적거나 같은(<=) 데이터가 있다면 true를 없다면 false를 리턴하는 메서드입니다.
userRepository.existsByStartDateLessThanEqual(LocalDateTime.now());

 

  • 세 번째는 대소문자를 무시하고 LIKE 쿼리를 날려서 해당되는 데이터의 수를 가져오는 예제로 아래와 같이 입력 변수에 "%" 부호를 원하는 위치에 포함하여 실행을 합니다.
userRepository.countByFirstnameIgnoreCaseLike("kim%");

 

쿼리 Subject 키워드

메서드 처음 시작 위치에 오는 키워드로 어떤 작업을 할 것이며, 어떤 데이터 타입을 리턴할지 결정됩니다.

  • findBy : List<User>와 같이 Collection 타입으로 리턴되나, 조회하는 대상이 Primary Key라면 아래와 같이 단일 객체로 리턴
Optional<User> user = userRepository.findById((long)3);

 

  • findFirst(숫자)By : findFirstBy..과 같이 숫자가 없다면 제일 첫 번째 데이터 1개가 리턴되고, 숫자가 있다면 Collection 타입으로 리턴
  • existBy : boolean 타입으로 리턴
  • countBy : int/long 등으로 해당되는 데이터 수 리턴
  • deleteBy : void 타입 혹은 int/long 등으로 삭제된 데이터 수 리턴

 

메서드명 내 키워드

메서드명 By 뒤에 작성되는 키워드로 SQL의 Where절 내 명령어와 같은 역할입니다. 아래 키워드 표는 스프링 공식 도큐먼트에 있는 내용입니다. 더 상세한 내용은 아래 공식문서를 참조하시면 됩니다.

참조 : https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods

키워드 샘플 JPQL
Distinct findDistinctByLastnameAndFirstname select distinct …​ where x.lastname = ?1 and x.firstname = ?2
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is, Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull, Null findByAge(Is)Null … where x.age is null
IsNotNull, NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection<Age> ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection<Age> ages) … where x.age not in ?1
TRUE findByActiveTrue() … where x.active = true
FALSE findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstname) = UPPER(?1)

 

 

반응형

댓글