본문 바로가기
Development/Spring

Spring Data JPA 쿼리메소드

by 메정 2021. 9. 25.

Spring Data JPA ?

spring framework에서 JPA를 편리하게 사용할 수 있도록 지원

  • CRUD 처리를 위한 공통 인터페이스 제공
  • repository 개발 시 인터페이스만 작성하면, 실행 시점에 spring data JPA가 구현 객체를 동적으로 생성해서 주입
  • 데이터 접근 게청(repository) 구현 시 클래스 없이 인터페이스만 작성하여 개발을 완료하도록 지원
  • 공통메소드는 spring data jpa가 제공하는 의존성 라이브러리에 포함되어 있음

사용하기 위해선

라이브러리를 의존성 추가해줘야 함 (build.gradle)

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

JpaRepository

Spring Data Jpa 모듈

    Repository 
        |
  CrudRepository 
        |
       ...
        |
  JpaRepository 

JpaRepository 인터페이스를 상속받으면 사용할 수 있는 주요 메서드

// em : EntityManager

  • save(S) : 새로운 엔티티는 저장하고, 이미 있는 엔티티는 수정
    • 내부에서 식별자 값이 없으면 em.persist(), 있으면 em.merge() 호출
  • delete(T) : 엔티티 하나 삭제
    • 내부에서 em.remove() 호출
  • findByOne(id) : 엔티티 1개를 id 값으로 조회
    • 내부에서 em.find() 호출
  • getOne(id) : 엔티티를 프록시로 조회
    • 내부에서 em.getReference() 호출
  • findAll() : 모든엔티티 조회 (sort, pagable 조건을 파라미터로 제공)

쿼리메소드 기능

JpaRepository 인터페이스를 상속한 Repository 계층의 클래스에 메소드의 이름으로 적절한 JPQL 쿼리를 생성하여 실행

JPQL?
선언한 도메인 클래스 +.(점) + 메서드 이름으로 Named쿼리
ex. select a from Account a where a.name = ?1

  • JPA가 제공하는 쿼리 메소드 기능
  • 메소드 이름으로 쿼리 생성 가능
  • JPA NamedQuery 호출
  • @Query 어노테이션을 사용하여 쿼리 직접 정의 가능

Spring Data JPA 쿼리 생성

  • 엔티티의 필드명 변경 시 인터페이스에 정의한 메소드명도 변경해주어야 함
    • 이 작업이 제대로 되지 않으면 처음 앱 실행 시 bean이 찾지 못할 수도 있음
      4
      5

ex.

@Repository
public interface PerformanceRepository extends JpaRepository<Performance, Long> {
        //startDate보다 같거나 큰(<=) 모든 모든 값을 startDate를 기준으로 오름차순으로 정렬하여 조회 
    List<Performance> findByStartDateGreaterThanEqualOrderByStartDateAsc(Date startDate);

        //title과 같으면서(and) startDate보다 같거나 큰(<=) 모든 모든 값을 startDate를 기준으로 오름차순으로 정렬하여 조회
    List<Performance> findByTitleAndStartDateGreaterThanEqualOrderByStartDate(String title, Date startDate);
}

JPA NamedQuery 호출

메소드 이름으로 Jpa Named 쿼리 호출이 가능하다.

@Repository
public interface PerformanceRepository extends JpaRepository<Performance, Long> {
        List<Performance> findByTitle(@Param("title") String title);
}
  • 쿼리에 이름을 부여하여 사용
  • 어노테이션이나 xml에 쿼리를 정의
  1. 어노테이션으로 정의

    @Entity 
    @NamedQuery( 
    name = "Performance.findByTitle" 
    query = "select p from Performance p where p.title = :title")
    public class Performance{ ... }
  2. xml로 정의

    <named-query name="Performance.findByTitle"> 
    <query><CDATA[ select p from Performance p where p.title = :title ]/></query>
    </named-query>
  3. 직접 쿼리 정의

    @Repository 
    public interface PerformanceRepository extends JpaRepository<Performance, Long> { 
    //1. 직접 쿼리 정의 @Query("select p from Performance p where p.title = :title") 
    List<Performance> findByTitle(String title); 
    
    //2. Native SQL 사용 @Query(value = "select m from Performance p where p.title = :title", nativeQuery = true) 
    List<Performance> findByTitle(String title); 
    }

    원하는 값만 매핑하여 return 하고 싶을 경우, Mapping에 관한 인터페이스를 따로 정의하거나 DTO를 만들어서 Repository의 메소드의 return 타입을 해당 값으로 지정해줘야 함

ex.

public interface PerformanceMapping {
    String getTitle();
    Date getStartDate();
    Date getEndDate();
    String getPrice();
    String getDescription();
    String getRunningTime();
}

//이런 식으로 원하는 값만 매핑해서 return 하도록
List<PerformanceMapping > findByStartDateGreaterThanEqualOrderByStartDateAsc(Date startDate);

참고

댓글