728x90
쿼리 메서드란
- repository interface에 선언되는 DB에서 정보를 찾는 메서드
spring data JPA가 제공하는 쿼리 메서드 기능
- 메서드 이름으로 쿼리 생성
- 메서드 이름으로 JPA NamedQuery 호출
- @Query 어노테이션을 사용하여 repository interface에 쿼리 직접 정의
메서드 이름으로 쿼리 생성
- spring data jpa를 사용하지 않는다면 작성해야할 JPQL
public List<Member> findByUsernameAndAge(String username, int age) {
return em.createQuery(
"select m from Member m" +
" where m.username = :username" +
" and m.age = :age", Member.class)
.setParameter("age", age)
.setParameter("username", username)
.getResultList();
}
@Test
void findByUsernameAndAge() throws Exception {
//given
Member m1 = new Member("AAA", 10);
Member m2 = new Member("AAA", 20);
memberJpaRepository.save(m1);
memberJpaRepository.save(m2);
//when
List<Member> result = memberJpaRepository.findByUsernameAndAge("AAA", 10);
//then
assertThat(result.get(0)).isEqualTo(m1);
}
- 위 코드를 작성하면 사진과 같은 쿼리가 나가게 된다(당연한 결과)
- 하지만 여기서 spring data jpa가 제공하는 "메서드 이름으로 쿼리 생성"을 사용해보자
List<Member> findByUsernameAndAge(String username, int age);
- 쿼리가 똑같이 작동하는 것을 알 수 있다
- 정해진 규칙에 따라 메서드 이름을 작성해야 spring data jpa가 해석하여 쿼리를 작성할 수 있음
만약에 메서드 이름을 규칙에 따라 작성하지 않는다면?
List<Member> findByUsernameasdAndAge(String username, int age);
- 애플리케이션을 실행하면 위와 같은 에러가 발생한다
- 질문 : spring data jpa가 어떻게 알고 쿼리를 자동으로 작성해줄까?
그 외 다른 쿼리 메서드
List<Member> findTop3By();
select member0_.member_id as member_i1_0_,
member0_.age as age2_0_,
member0_.team_id as team_id4_0_,
member0_.username as username3_0_
from member member0_ limit 3;
- 해당 기능은 엔티티의 필드명이 변경되면 메서드 이름도 "함께 변경"해야한다
JPA NamedQuery
@NamedQuery(
name="Member.findByUsername",
query="select m from Member m where m.username = :username"
)
public class Member {}
- JPA를 직접 사용하여 Named 쿼리를 호출
public List<Member> findByUsername(String username) {
return em.createNamedQuery("Member.findByUsername", Member.class)
.setParameter("username", username)
.getResultList();
}
- spring data jpa를 사용하여 Named 쿼리 호출
public interface MemberRepository extends JpaRepository<Member, Long>{
@Query(name = "Member.findByUsername")
List<Member> findByUsername(@Param("username") String username);
}
- Query 어노테이션을 생략하고도 Named 쿼리 호출할 수 있다
public interface MemberRepository extends JpaRepository<Member, Long>{
//@Query(name = "Member.findByUsername")
List<Member> findByUsername(@Param("username") String username);
}
- 왜 가능할까?
- 제네릭에서 해당 repository에 저장할 도메인은 Member로 정했다
- 그러면 Member.findByUsername이라는 NameQuery를 먼저 찾는다
- 즉, spring data jpa가 쿼리 메서드를 실행할 때 우선순위가 있다는 것을 의미한다
- 첫번째로 해당 도메인에 있는 NamedQuery를 먼저 찾고,
- 두번째로 NamedQuery가 없다면 처음에 배웠던 property 이름을 가지고 생성하는 메서드가 실행된다
- 우선순위를 변경할 수 있다고 한다!
- keyword : query lookup strategies
@Query, 메서드에 쿼리 직접 정의
- 실행할 메서드에 정적 쿼리를 직접 작성
- 이름 없는 Named Query라고 할 수 있음
- 애플리케이션 실행 시점에 문법 오류를 발견할 수 있음
- 매우 큰 장점
public interface MemberRepository extends JpaRepository<Member, Long>{
@Query("select m from Member m where m.username = :username and m.age = :age")
List<Member> findUser(@Param("username") String username, @Param("age") int age);
}
@NamedQuery는 실무에서 잘 사용하지 않는다?
- 강의에서 Named Query는 실제로 사용하지 않는다고 함
- 복잡한 정적 쿼리는 마지막에 배웠던 "메서드에 쿼리 직접 정의"를 사용하고
- 간단한 정적 쿼리는 처음에 배웠던 "메서드 이름으로 쿼리 생성"을 사용함
@Query를 이용하여 DTO 조회
빨강색은 MemberDto 클래스의 경로를 의미하고, 파랑색은 MemberDto의 생성자 형식을 의미한다.
REFERENCES
728x90
'Spring 강의 > Spring data JPA' 카테고리의 다른 글
@EntityGraph (0) | 2022.04.13 |
---|---|
벌크 연산 (0) | 2022.04.12 |
페이징과 정렬 (0) | 2022.04.11 |