Spring Data JPA Projections

2023. 4. 24. 21:13·Spring

Spring Data JPA를 이용해 개발하던 중 모든 컬럼을 조회할 필요없이 특정 컬럼만 조회하면 되는 경우가 생겼다.

이런 경우 Projection을 사용하는데, 정확한 사용법을 알아보자.

class Person {

  @Id UUID id;
  String firstname, lastname;
  Address address;

  static class Address {
    String zipCode, city, street;
  }
}

interface PersonRepository extends Repository<Person, UUID> {

  Collection<Person> findByLastname(String lastname);
}

Interface-based Projections

위와 같은 코드에서 이름만 필요한 경우 Interface-based Projections 을 사용할 수 있다.

사용법은 아래 코드와 같이 해당 속성을 읽을 수 있도록 하는 접근 메서드를 선언한 인터페이스를 이용하는 것이다.

주의할 점은 aggregate root의 속성값과 같게 적어줘야한다!

aggregate root : 해당 repository에서 사용하는 entity를 의미(정확한 개념은 추가공부 필요)

interface NamesOnly {
  String getFirstname();
  String getLastname();
}
interface PersonRepository extends Repository<Person, UUID> {

  Collection<NamesOnly> findByLastname(String lastname);
}

쿼리 실행 엔진은 런타임 시점에 해당 인터페이스에 대한 프록시 객체를 만들고 접근 메서드에 대한 호출을 해당 객체로 전달한다.

 

재귀적 사용

projections는 재귀적으로 사용이 가능하다.

interface PersonSummary {

  String getFirstname();
  String getLastname();
  AddressSummary getAddress();

  interface AddressSummary {
    String getCity();
  }
}

 

Closed Projections

aggregate와 속성이 일치하는 인터페이스는 Closed Projection이다.

Closed Projection을 사용하면 프록시에 필요한 모든 속성을 알기 때문에 쿼리 실행 최적화가 가능하다.

//Closed Projection
interface NamesOnly {

  String getFirstname();
  String getLastname();
}

//Open Projection
interface NamesOnly {

  @Value("#{target.firstname + ' ' + target.lastname}")
  String getFullName();
  …
}

 

Class-based Projections (DTOs)

프록시가 발생하지 않으며 재귀적인 Projection을 사용할 수 없다는 것 빼고는 인터페스 기반 projection과 같다.

생성자의 매개변수 이름으로 값을 읽을 필드를 결정한다.

class NamesOnly {

  private final String firstname, lastname;

  NamesOnly(String firstname, String lastname) {

    this.firstname = firstname;
    this.lastname = lastname;
  }

  String getFirstname() {
    return this.firstname;
  }

  String getLastname() {
    return this.lastname;
  }

  // equals(…) and hashCode() implementations
}

주의할 점으로 클래스 기반 projection은 JPQL의 native 쿼리와 사용할 수 없다.

 

출처

 

Spring Data JPA - Reference Documentation

Example 119. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del

docs.spring.io

 

'Spring' 카테고리의 다른 글

CustomOidcUserService 구현  (0) 2025.09.09
프레임워크를 사용하는 이유  (0) 2023.10.06
@Transactional의 작동 방식과 롤백되지 않는 문제(Checked Exception)  (0) 2023.08.31
'Spring' 카테고리의 다른 글
  • CustomOidcUserService 구현
  • 프레임워크를 사용하는 이유
  • @Transactional의 작동 방식과 롤백되지 않는 문제(Checked Exception)
연잔
연잔
  • 연잔
    Bit by Bit
    연잔
  • 전체
    오늘
    어제
    • 분류 전체보기
      • TIL
      • 생각정리
      • JAVA
      • Spring
      • Database
      • 운영체제
      • 네트워크
      • WEB
      • Docker
      • Jenkins
      • DevOps
      • git
      • Etc
        • Error
      • html, css
      • 프로젝트
        • MoaaMoaa
        • TEDbear
        • ChePo
      • Book
        • 클린 코드
        • 클린아키텍처
        • 데이터 중심 애플리케이션 설계
        • IT 엔지니어를 위한 네트워크 입문
        • 주니어가 반드시 알아야할 실무지식
      • SSAFYcial
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    인터넷
    HTML
    Algolithm
    HTTP
    SSAFY
    algorithm
    싸피
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
연잔
Spring Data JPA Projections
상단으로

티스토리툴바