[Spring Data JPA] Projections 과 Native QueryBack-End/JPA2024. 8. 16. 00:16
Table of Contents
이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.
Projections
Projections는 Spring Data JPA에서 특정 엔티티의 일부 필드만을 선택적으로 조회하기 위해 사용하는 기능이다. Projections를 통해 전체 엔티티를 조회하지 않고 필요한 필드만을 선택적으로 가져올 수 있으며, 이를 통해 성능을 최적화하고 데이터 전송량을 줄일 수 있다.
인터페이스 기반 프로젝션 (Interface-based Projection)
- 프로젝션을 위해 인터페이스를 정의하고, 필요한 필드만 메서드로 선언한다.
- JPA는 이 인터페이스를 구현하는 프록시 객체를 생성하여, 쿼리 결과를 이 인터페이스의 구현체로 반환한다.
public interface UsernameOnly {
String getUsername();
}
조회할 엔티티의 필드를 getter 형식으로 지정하면 해당 필드만 선택해서 조회(Projection)
public interface MemberRepository extends JpaRepository<Member, Long> {
//...
List<UsernameOnly> findProjectionsByUsername(String username);
}
메서드 이름은 자유, 반환 타입으로 인지
@Test
public void projections() throws Exception {
//given
Team teamA = new Team("teamA");
em.persist(teamA);
Member m1 = new Member("m1", 0, teamA);
Member m2 = new Member("m2", 0, teamA);
em.persist(m1);
em.persist(m2);
em.flush();
em.clear();
//when
List<UsernameOnly> result = memberRepository.findProjectionsByUsername("m1");
//then
Assertions.assertThat(result.size()).isEqualTo(1);
}
실제 SQL에서도 select절에서 username만 조회(Projection)하는 것을 확인할 수 있다.
클래스 기반 프로젝션 (Class-based Projection)
- DTO(Data Transfer Object) 클래스를 정의하고, 생성자를 통해 필요한 필드를 전달받아 프로젝션 결과를 매핑한다.
- 이 방법은 주로 명시적인 매핑이 필요할 때 사용된다.
public class UsernameOnlyDto {
private final String username;
public UsernameOnlyDto(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
}
public interface MemberRepository extends JpaRepository<Member, Long> {
//...
List<UsernameOnlyDto> findProjectionsByUsername(String username);
}
Native Query
가급적 네이티브 쿼리는 사용하지 않는게 좋음, 정말 어쩔 수 없을 때 사용
최근에 나온 궁극의 방법은 스프링 데이터 Projections과 함께 사용하는 것
스프링 데이터 JPA 기반 네이티브 쿼리
- 페이징 지원
- 반환 타입
-Object[]
-Tuple
-DTO(스프링 데이터 인터페이스 Projections 지원) - 제약
-Sort 파라미터를 통한 정렬이 정상 동작하지 않을 수 있음(믿지 말고 직접 처리)
-JPQL처럼 애플리케이션 로딩 시점에 문법 확인 불가
-동적 쿼리 불가
네이티브 쿼리
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query(value = "select * from member where username = ?", nativeQuery = true)
Member findByNativeQuery(String username);
}
프로젝션 활용
스프링 데이터 JPA 네이티브 쿼리 + 인터페이스 기반 Projections 활용하여 DTO로 반환
@Query(value = "SELECT m.member_id as id, m.username, t.name as teamName " +
"FROM member m left join team t ON m.team_id = t.team_id",
countQuery = "SELECT count(*) from member",
nativeQuery = true)
Page<MemberProjection> findByNativeProjection(Pageable pageable);
'Back-End > JPA' 카테고리의 다른 글
[JPA]PostgreSQL 사용시, 엔티티에 Enum 매핑 오류 (0) | 2024.11.21 |
---|---|
[Spring Data JPA] 새로운 엔티티인지 구별하는 방법 (0) | 2024.08.15 |
[Spring Data JPA] 확장 기능 (0) | 2024.08.14 |
[Spring Data JPA] 쿼리 메서드 기능 (0) | 2024.08.13 |
[Spring Data JPA] Spring Data JPA (0) | 2024.08.12 |