[Spring Data JPA] 쿼리 메서드 기능

2023. 1. 26. 13:19Spring

쿼리 메서드 기능 중 메서드 이름만으로 쿼리를 생성하는 기능이 있습니다. 인터페이스에 메서드만 선언하면 해당 메서드가 이름으로 적절한 JPQL 쿼리를 생성해서 실행합니다.

 

 

Spring Data JPA가 제공하는 쿼리 메소드 기능은 크게 3가지입니다.

  • 메서드 이름으로 쿼리 생성
  • 메서드 이름으로 JPA Named 쿼리, Named 네이티브 쿼리 호출
  • @Query 어노테이션을 사용해서 리포지토리 인터페이스에 쿼리 직접 정의 

 

@Query 어노테이션을 사용해서 리포지토리 인터페이스에 쿼리 직접 정의 하는 건 토이플젝에서 늘 하던 방식이므로

이번 포스팅에서느 메서드 이름으로 쿼리 생성에 대해 자세하게 살펴보도록 하겠습니다.

 

 

[ 메소드 이름으로 쿼리 생성 ]

토이프로젝트로 웹 애플리케이션을 만들 때 로그인 input에는 이메일과 이름을 기입해야 한다고 가정해 봅시다.

그럴 때 이메일과 이름을 조회하려면 다음과 같은 메서드를 정의하면 됩니다.

public interface UserRepository extends Repository<User, Long> {
	List<User> findByEmailAndName(String email, String name);
}

 

findByEmailAndName()를 실행하면 Spring Data JPA는 규칙에 맞게 분석해서 적절한 JPQL을 생성하고 실행합니다. 

 

실행된 JPQL은 다음과 같습니다.

select u from User u where u.email = ?1 and u.name =?2

 

 

 

메소드 이름 짓는 규칙만 잘 지켜준다면 원하는 쿼리를 자동으로 쉽게 뽑아줄 수 있습니다. 

 

Spring Data JPA공식문서가 제공하는 표를 보면 기능을 어떻게 사용해야 하는지 알 수 있습니다.

키워드 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)

 

[참고] Spring Data JPA공식문서

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

 

Spring Data JPA - Reference Documentation

Example 119. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del

docs.spring.io

 

 

여기서 주의해야 할 점은, 만약에 엔티티의 필드명이 변경되면 인터페이스에 정의한 메서드 이름도 함께 변경해주어야 합니다.

 

 

 

 

 

 

❗❗ 헷갈리는 개념 정리 ❗❗
1. custom query (JPQL 문법)
class name, field name 사용

2. native query (SQL문법)
table name, column name 사용

nativeQuery속성이 false면 JPQL, true면 SQL입니다.
@Query("SELECT m FROM Member m") // JPQL
@Query("SELECT m.* FROM Member m", nativeQuery = true) // SQL