쿼리 메소드 기능 3가지
- 메소드이름으로 쿼리생성
- 메소드이름으로 JPA NamedQuery 호출
- @Query 어노테이션을 활용하여 리파지토리 인터페이스에 쿼리 직접 정의
예제
public List<Member> findByName(String name){
return em.createQuery("select m from Member m where m.name=:name", Member.class)
.setParameter("name",name).getResultList();
}
해당 소스는 순수JPA 리포지토리를 이용한 JPQL임 .
쿼리 메소드는 Repository 인터페이스에 간단한 네이밍 룰을 이용하여 메소드를 작성하면 원하는 쿼리를 실행할 수 있음.
Data JPA의 메소드이름 쿼리생성방식으로 변경하면 쉽게 소스를 줄일수 있음.
public interface MemberDataJpaRepository extends JpaRepository<Member, Long> {
List<Member> findByName(String name);
}
먼저 인터페이스에서 JPA레포지토리를 상속함(엔티티명, 엔티티식별자 타입);
메소드명에서 by는 where 절을 뜻함. 그밖에 각종 메소드명명 규칙은 다음 표 와 링크 참고
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) |
다음은 @NamedQuery 사용법
@NamedQuery 어노테이션으로 쿼리에 이름을 부여 및 정의하여 호출, 사용한다. 엔티티의 쿼리를 선언해야해서 그닥 가독성이 좋은 방법은 아닌것 같지만 일단 예제는 만들어보았다.
@NamedQuery(
name="Member.findByName",
query="select m from Member m where m.username = :username"
)
public class Member extends BaseEntity{
public interface MemberDataJpaRepository extends JpaRepository<Member, Long> {
@Query(name = "Member.findByName") // 선언을 하지 않아도 spring data jpa가 알아서 관례상 찾아 넣어주긴 함
List<Member> findByName(@Param("username") String username);
}
엔티티에 쿼리를 정의하고 리포지토리에서 @Query로 호출하면 된다고한다.
복습하면서 기록하는거긴한데 확실히 그전에 공부할때 대강 보고 넘어가서 기억이 잘 안났다. 알아만 두도록해야겠다.
마지막으론 @Query어노테이션에 직접 쿼리를 정의하는방식이다.
public interface MemberDataJpaRepository extends JpaRepository<Member, Long> {
@Query("select m from Member m where m.name= :name")
List<Member> findByName(@Param("name") String username);
}
제일 직관적이고 이방법 역시 컴파일시점에 에러를 잡아줘서 굉장히 효율적인 것 같다. 일단 첫번째 메소드이름으로 정의하면
파라미터와 조건이 많아질수록 메소드의 이름이 명명규칙에 의해 길어지기때문에 가독성이 매우 떨어지게된다.
Data JPA를 잘 활용하면 순수 jpa jpql 보다 훨씬 간편하게 구현 할 수 있다.
'JPA' 카테고리의 다른 글
Data JPA collection 파라미터 바인딩 (0) | 2023.10.11 |
---|---|
@Query 값, DTO로 반환받기 (0) | 2023.10.11 |
변경감지 (0) | 2023.10.06 |
Join vs Fetch Join (1) | 2023.10.04 |
즉시로딩 과 지연로딩 그리고 N+1 (0) | 2023.09.20 |