엔티티 대신에 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해서 결과를 반환해준다.
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);
<>안에 해당 인터페이스 이름을 넣어주면 된다.
쿼리는 인터페이스 기반과 동일하게 생성된다.
연관관계에 있는 엔티티까지 조회하고 싶다면?
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해서 엔티티로 조회한 다음에 계산)