SpringDataJPA - 쿼리 메소드 기능

박민수·2023년 11월 14일
0

JPA

목록 보기
13/24
post-thumbnail

쿼리 메소드 기능

스프링 데이터 JPA가 제공하는 쿼리 메서드 기능을 살펴보자.

  1. 메소드 이름으로 쿼리 생성
  2. 메소드 이름으로 JPA NamedQuery 호출
  3. @Query 어노테이션을 사용해서 리포지토리 인터페이스에 쿼리 직접 정의

메소드 이름으로 쿼리 생성

스프링 데이터 JPA는 메소드 이름을 분석해서 JPQL을 생성하고 실행한다. 이름과 나이를 기준으로 회원을 조회해보자.

public interface MemberRepository extends JpaRepository<Member, Long> {
    List<Member> findByUsernameAndAgeGreaterThan(String username, int age);
}
  • 조회 쿼리 : find...By, read...By, query...By, get...By
  • COUNT 쿼리 : count...By... (반환타입 long)
  • EXISTS 쿼리 : exists...By... (반환타입 boolean)
  • DELETE 쿼리 : delete...By, remove...By (반환타입 long)
  • DISTINCT : findDistinct, findMemberDistinctBy
  • LIMIT : findFirst3, findFirst, findTop, findTop3

자세한 쿼리 메소드 필터 조건은 링크를 참고하자.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation

참고: 이 기능은 엔티티의 필드명이 변경되면 인터페이스에 정의한 메서드 이름도 꼭 함께 변경해야 한다. 그렇지 않으면 애플리케이션 시작하는 시점에 오류가 발생한다. 이렇게 애플리케이션 로딩 시점에 인지할 수 있는 것이 스프링 데이터 JPA의 매우 큰 장점이다.

NamedQuery 호출

메소드 이름으로 NamedQuery를 호출할 수 있다.

Named 쿼리 정의

@Entity
@NamedQuery(name="Member.findByUsername", query="select m from Member m where m.username = :username")
public class Member {
}

Named 쿼리 호출 (JPA)

public class MemberRepository {
    public List<Member> findByUsername(String username) {
    ...
        List<Member> resultList =
            em.createNamedQuery("Member.findByUsername", Member.class)
                .setParameter("username", username)
                .getResultList();
        }
}

Named 쿼리 사용 (SpringDataJPA)

@Query(name = "Member.findByUsername")
List<Member> findByUsername(@Param("username") String username);

+) @Query를 생략하고 메서드 이름만으로 Named 쿼리를 호출할 수 있다.

public interface MemberRepository extends JpaRepository<Member, Long> {
    List<Member> findByUsername(@Param("username") String username);
}

스프링 데이터 JPA는 선언한 "도메인 클래스 + .(점) + 메서드 이름"으로 Named 쿼리를 찾아서 실행한다. 만약 실행할 Named 쿼리가 없으면 메서드 이름으로 쿼리 생성 전략을 사용한다.

참고: 스프링 데이터 JPA를 사용하면 실무에서 Named Query를 직접 등록해서 사용하는 일은 드물다. 대신 @Query 를 사용해서 리포지토리 메소드에 쿼리를 직접 정의한다.

메소드에 쿼리 정의

해당 기능은 실행할 메서드에 정적 쿼리를 직접 작성하므로, 이름 없는 Named 쿼리라 할 수 있다. JPA Named 쿼리처럼 애플리케이션 실행 시점에 문법 오류를 발견할 수 있다는 장점이 있다.

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") intage);
}

참고: 실무에서는 메소드 이름으로 쿼리 생성 기능은 파라미터가 증가하면 메서드 이름이 매우 지저분해진다. 따라서 @Query 기능을 자주 사용하게 된다.

profile
안녕하세요 백엔드 개발자입니다.

0개의 댓글