Spring Data JPA 쿼리메소드 - comento-backend-camp/ticket-reservation-server-hyejung GitHub Wiki

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);

참고

⚠️ **GitHub.com Fallback** ⚠️