2 분 소요


목차

  • 메소드 이름으로 쿼리 생성
  • NamedQuery
  • @Query - Repository 메소드에 쿼리 정의

쿼리 메소드 기능 3가지

  • 메소드 이름으로 쿼리 생성
  • 메소드 이름으로 JPA NamedQuery 호출
  • @Query 어노테이션을 사용해서 Repository 인터페이스에 쿼리 직접 정의


메소드 이름으로 쿼리 생성

메소드 이름을 분석해서 JPQL 쿼리 실행

순수 JPA Repository

public List<Member> findByUsernameAndAgeGreaterThan(String username, int age) {
    return em.createQuery(
        "select m from Member m where m.username = :username and m.age > :age")
        .setParameter("username", username)
        .setParameter("age", age)
        .getResultList();
}
  • 파라미터로 넘어오는 이름과 같으며 넘어온 age보다 나이가 더 많은 Member만 return

스프링 데이터 JPA

public interface MemberRepository extends JpaRepository<Member, Long> {
    List<Member> findByUsernameAndAgeGreaterThan(String username, int age);
}
  • 스프링 데이터 JPA는 메소드 이름을 분석해서 JPQL을 생성하고 실행

쿼리 메소드 필터 조건
스프링 데이터 JPA 공식 문서 참고

스프링 데이터 JPA가 제공하는 쿼리 메소드 기능

  • 조회 : find…By, read…By, query…By, get…By ..
    • Ex) findHelloBy 처럼 (…)에 식별하기 위한 내용(설명)이 들어가도 된다.
  • COUNT : count…By 반환타입 long
  • EXISTS : exists…By 반환타입 boolean
  • 삭제 : delete…By, remove…By 반환타입 long
  • DISTINCT : findDistinct, findMemberDistinctBy
  • LIMIT : findFirst3, findFirst, findTop, findTop3

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


JPA NamedQuery(중요X)

@NamedQuery 어노테이션으로 Named 쿼리 정의

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

JPA를 직접 사용하여 호출

public List<Member> findByUsername(String username) {
    ...
    return em.createQuery("Member.findUsername", Member.class)
                .setParameter("username", username)
                .getResultList();
}

스프링 데이터 JPA

@Query(name = "Member.findByUsername")
List<Member> findByUsername(@Param("username") String username);
  • @Query를 생략하고 메서드 이름만으로 Named 쿼리를 호출할 수 있다.
    • 스프링 데이터 JPA는 선언한 “도메인 클래스 + .(점) + 메서드 이름”으로 Named 쿼리를 찾아서 실행
  • 만약 실행할 Named 쿼리가 없으면 메서드 이름으로 쿼리 생성 전략을 사용한다.

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


@Query

Repository 메소드에 쿼리 정의

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);
}
  • @org.springframework.data.jpa.repository.Query 어노테이션을 사용
  • 실행할 메서드에 정적 쿼리를 직접 작성하므로 이름 없는 Named 쿼리라 할 수 있음
  • JPA Named 쿼리처럼 애플리케이션 실행 시점에 문법 오류를 발견할 수 있음(매우 큰 장점!)

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

@Query, 값, DTO 조회

단순히 값 하나를 조회

@Query("select m.username from Member m")
List<String> findUsernameList();

JPA 값 타입(@Embedded)도 이 방식으로 조회할 수 있다.

DTO로 직접 조회

@Query("select new study.datajpa.dto.MemberDto(m.id, m.username, t.name)" +
        "from Member m join m.team t")
List<MemberDto> findMemberDto();

DTO로 직접 조회하려면 JPA의 new 명령어를 사용해야 한다. 그리고 다음과 같이 생성자가 맞는 DTO가 필요하다.(JPA와 사용방식이 동일.)


<출처 : 인프런 - 실전! 스프링 데이터 JPA(김영한)>

댓글남기기