2025 09 30
2025-09-30¶
Spring Data JPA projections¶
- 개요
- Spring Data 쿼리는 주로 1개/여러개의 인스턴스를 리포지토리에서 반환
- 특정 프로젝션 (쿼리 결과를 특정한 데이터 구조에 매핑) 이 필요할 때가 있음
-
Interface-based Projections
- 쿼리 결과를 특정 이름 속성에 매핑하는 가장 쉬운 방법은, 인터페이스를 선언하여 getter를 열어두는 것
- Query Execution Engine에서 런타임에 프록시 인스턴스 만들어서 해당 메서드 쓸 수 있도록 제공
- 재귀적으로 interface안에 interface 넣어서 정의해도 사용 가능
Closed Projections- interface의 getter가 타겟 프로퍼티에 꼭 맞으면 Closed Projection이라고 지칭
- 해당 속성을 이미 알고 있기 때문에, Spring Data가 쿼리 실행 최적화 함.
-
Open Projections@Value를 사용해서 값을 조작해서 들고 올수도 있는 듯
- 해당 값은 너무 복잡하게 쓰지 마시고, interface의 default 메서드를 쓰는 것도 좋은 방법
- Class-based Projections (DTOs)
- interface 사용과 완전히 동일한 방식이지만, 프록싱(당연)과 nested projection이 없음
- Java의 record를 많이 사용
- 모든 필드 private final, equals/hashCode/toString 선 정의 되어있음
- 필요하다면, 제네릭을 사용하여 Dynamic Projection도 사용 가능
interface PersonRepository extends Repository<Person, UUID> { <T> Collection<T> findByLastname(String lastname, Class<T> type); } void someMethod(PersonRepository peopleRepository) { Collection<Person> aggregates = peopleRepository.findByLastname("Matthews", Person.class); Collection<NamesOnly> aggregates = peopleRepository.findByLastname("Matthews", NamesOnly.class); }
-
JPA와 Projection
- Spring Data JPA는 주로 튜플쿼리(필요한 필드만 조회)를 통한 interface-based Projections 지원
1. JPA Derived Queries
- 메서드 이름으로 쿼리 만드는 방식
- 반환 타입 보고 interface/class based projection 지원
- 클래스 기반 프로젝션은 JPA의 생성자 표현식 따라감
- interface-based:
Tuple+ 프록시 방식 - class-based:
SELECT new com.example.NamesOnlyDto(p.firstname, p.lastname) FROM Person p ...2. 문자열 기반 (@Query)
- interface-based:
- JPQL과 class-based projection 쓸 때는 new 생성자로 매핑
- 다만, 엔티티 전체를 조회하는 것 처럼 작성해도 스프링이 실제 DTO 타입보고 자체적으로 변환해줄 수도 있음.
- Native Query
@SqlResultSetMapping를 사용할수도 있음. SQL 결과셋을 여기에 매핑해줘 표현
- Spring Data JPA는 주로 튜플쿼리(필요한 필드만 조회)를 통한 interface-based Projections 지원
1. JPA Derived Queries