쿼리 메서드 기능 - 1
스프링 데이터 JPA가 제공하는 쿼리 메서드 기능
메서드 이름으로 쿼리 생성
메서드 이름으로 JPA NamedQuery 호출
@Query어노테이션을 사용해서 레포지토리 인터페이스에 쿼리 직접 정의
메서드 이름으로 쿼리 생성
순수 JPA
public List<Member> findByUsernameAndAgeGreaterThan(String username, int age) {
return em.createQuery("select m from Member m where m.username = :username and m.age > :age",Member.class)
.setParameter("username", username)
.setParameter("age", age)
.getResultList();
}스프링 데이터 JPA
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom {
List<Member> findByUsernameAndAgeGreaterThan(String username, int age);
}스프링 데이터 JPA가 메서드 이름을 분석해서 JPQL을 생성하고 실행한다. 물론 정해진 규칙이 있다. 스프링 데이터 JPA 공식 문서
엔티티의 필드명이 변경되면 인터페이스의 정의한 메서드 이름도 꼭 함께 변경되어야 한다. 그렇지 않으면 애플리케이션을 시작하는 시점에 오류가 발생한다.
애플리케이션 로딩 시점에 오류를 잡을 수 있는 것이 스프링 데이터 JPA의 매우 큰 장점이다.
JPA NamedQuery
엔티티에 NamedQuery 정의
JpaRepository
@Query를 사용하거나 생략해서 사용할 수 있다.
스프링 데이터 JPA는 전략이 있는데
선언한 "도메인 클래스 +
.(점) + 메서드 이름"으로 NamedQuery를 찾아서 실행한다.실행할 NamedQuery가 없으면 메서드 이름으로 쿼리 생성 전략을 사용한다.
이렇게 직접 NamedQuery를 등록해서 사용하는 일은 드물고 보통은
@Query를 사용해서 레포지토리 메서드에 직접 정의하는 방식을 많이 사용한다.
@Query, 레포지토리 메서드에 쿼리 정의
실행할 메서드에 정적 쿼리를 직접 작성하는 방식이다. 이름 없는 NamedQuery인 셈이다.
메서드에 JPQL 쿼리 작성
메서드 이름으로 쿼리 생성 기능은 파라미터가 증가하면 자연스럽게 메서드 이름이 길어질 수밖에 없으므로 메서드 이름이 지저분해진다. @Query로 메서드 이름을 줄일 수 있다.
애플리케이션 실행 시점에 문법 오류를 발견할 수 있다.
@Query로 값 조회하기
JPA 값 타입(@Embedded)도 이 방식으로 조회할 수 있다.
@Query로 DTO 조회하기
JPA 사용방식과 동일하게 new 명령어로 DTO로 직접 조회할 수 있다.
파라미터 바인딩
스프링 데이터 JPA는 위치 기반, 이름 기반 파라미터 바인딩을 지원한다.
기본 값은 위치 기반이고 이름 기반은 @Param으로 매핑한다.
이름 기반 파라미터를 사용하자. 코드 가독성도 좋고 무엇보다 유지보수에 용이해진다.
Collection타입으로in절도 지원한다.
반환 타입
스프링 데이터 JPA는 유연한 반환 타입을 지원한다.
조회 결과가 많거나 없을 때
컬렉션
결과 없음 : 빈 컬렉션을 반환한다.
단건 조회
결과 없음 :
null을 반환한다.결과가 두 건 이상 :
jakarta.persistence.NonUniqueResultException예외가 발생한다.
단건으로 지정한 메서드를 호출하면 스프링 데이터 JPA는 내부에서 JPQL의
Query.getSingleResult()메서드를 호출한다. 이 메서드를 호출했을 때 조회 결과가 없으면jakarta.persistence.NoResultException예외가 발생한다.이 때 스프링 데이터 JPA는 단건을 조회할 때 이 예외가 발생하면 예외를 무시하고 대신에
null을 반환한다.
Last updated