[Spring] Data JPA Projections

박준형·2023년 11월 30일
0

Spring

목록 보기
13/17
post-thumbnail

📌인터페이스 기반 Projections

엔티티 대신에 DTO를 편리하게 조회할 때 사용된다.

전체 엔티티가 아닌 회원이름만 조회하고 싶다면?

public interface UsernameOnly {
    String getUsername();
}

인터페이스를 만들고

List<UsernameOnly> findProjectionsByUsername(@Param("username") String username);

<>안에 해당 인터페이스 이름을 넣어주면 된다.

테스트 코드

	@Test
    public void projections() {
        //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");

        for (UsernameOnly usernameOnly : result) {
            System.out.println("usernameOnly = " + usernameOnly.getUsername());
        }
    }

JPA가 생성한 쿼리

select member0_.username as col_0_0_ from member member0_ where member0_.username='m1';

username만 select해서 결과를 반환해준다.


📌클래스 기반 Projections

public class UsernameOnlyDto {
    private final String username;

    public UsernameOnlyDto(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }
}

클래스를 만들고

List<UsernameOnlyDto> findProjectionsByUsername(@Param("username") String username);

<>안에 해당 인터페이스 이름을 넣어주면 된다.

쿼리는 인터페이스 기반과 동일하게 생성된다.


📌중첩 Projections

연관관계에 있는 엔티티까지 조회하고 싶다면?

public interface NestedCloseProjections {
    String getUsername();
    TeamInfo getTeam();

    interface TeamInfo {
        String getName();
    }
}

인터페이스를 구현하고

List<NestedCloseProjections> findProjectionsByUsername(@Param("username") String username);

<>안에 해당 인터페이스 이름을 넣어주면 된다.

JPA가 생성한 쿼리

select 
member0_.username as col_0_0_, 
team1_.team_id as col_1_0_, 
team1_.team_id as team_id1_2_, 
team1_.created_date as created_2_2_, 
team1_.last_modified_date as last_mod3_2_, 
team1_.created_by as created_4_2_, 
team1_.last_modified_by as last_mod5_2_, 
team1_.name as name6_2_ 

from member member0_ left outer join team team1_ on member0_.team_id=team1_.team_id 

where member0_.username='m1';

✅특징

Member의 username만 가져오는것은 최적화가 되었지만 두번째 팀 이름을 가져오는 부분은 최적화가 되지 않고 Team 엔티티 전체를 select 하게 된다.

  • projection의 대상이 root 엔티티면, JPQL SELECT절 최적화가 가능하다.
  • projection의 대상이 root 엔티티가 아니면 LEFT OUTER JOIN 으로 처리한다.
    (모든 필드를 SELECT해서 엔티티로 조회한 다음에 계산)
profile
으쌰 으쌰

0개의 댓글

관련 채용 정보