Spring Data JPA - QueryDSL Projection 방법
목차
select절에 조회 대상을 지정하는 것을 프로젝션 이라고 합니다.
프로젝션을 하는 여러 방법에 대해서 알아보도록 하겠습니다.
전체 또는 일부 컬럼 Projection
QMember member = QMember.Member;
List<Member> result = jpaQueryFactory.select(member)
.from(member)
.fetch();
List<String> result = jpaQueryFactory.select(member.name)
.from(member)
.fetch();
List<Tuple> result = jpaQueryFactory.select(member.name, member.addr)
.from(member)
.fetch();
fetch의 리턴 타입이 List<T> 타입 이기 때문에 select에 넘겨주는 파라미터의 타입에 따라 리턴 타입이 결정 됩니다.
member 전체를 Projection하면 member 타입, String 컬럼 하나는 String, 여러 값의 경우에는 Tuple 타입으로 리턴을 하게 됩니다.
특정 객체로 Projection
위와 같이 엔티티나 특정 컬럼의 타입이 아닌 특정 객체로 Projection 하는 방법을 알아보겠습니다.
Bean population( Projections )
Projections에서는 객체를 생성하는 3가지 방법을 제공해줍니다.
1. 프로퍼티 직접 접근( Setter )
@Getter
@Setter
public class MemberDTO{
String name;
String id;
String addr;
public MemberDTO(String name, String id, String addr){
this.name = name;
this.id = id;
this.addr = addr;
}
}
QMember member = QMember.member;
List<MemberDTO> result = jpaQueryFactory.select(
Projections.bean(MemberDTO.class,
member.name,
member.id,
member.sido.concat(" ").concat(member.sgng).concat(" ").concat(member.street).as("addr"))
.from(member)
.fetch();
쿼리 결과와 매핑할 프로퍼티의 이름이 다르면 as를 사용하여 결과를 매핑할 프로퍼티를 지정해주면 됩니다.
2. 필드 직접 접근( 멤버 변수 )
List<MemberDTO> result = jpaQueryFactory.select(
Projections.fields(MemberDTO.class,
member.name,
member.id,
member.sido.concat(" ").concat(member.sgng).concat(" ").concat(member.street).as("addr"))
.from(member)
.fetch();
Projections.fields 메소드를 사용하면 필드를 직접 접근하여 값을 채워주며, 필드가 private 여도 동작합니다.
3. 생성자 사용
List<MemberDTO> result = jpaQueryFactory.select(
Projections.constructor(MemberDTO.class,
member.name,
member.id,
member.sido.concat(" ").concat(member.sgng).concat(" ").concat(member.street))
.from(member)
.fetch();
생성자에 @QueryProjection 을 지정해주고, Projections.constructor 메소드를 사용하여 생성자를 사용할 수 있습니다.
Q DTO 클래스 사용( @QueryProjection )
DTO를 Q Class로 만들고, 생성자에 @QueryProjection을 사용해서도 프로젝션을 할 수 있습니다.
@Getter
@Setter
public class MemberDTO{
String name;
String id;
String addr;
@QueryProjection
public MemberDTO(String name, String id, String addr){
this.name = name;
this.id = id;
this.addr = addr;
}
}
QMember member = QMember.member;
List<MemberDTO> result = jpaQueryFactory.select(
new QMemberDTO(member.name,
member.id,
member.sido.concat(" ").concat(member.sgng).concat(" ").concat(member.street).as("addr"))
.from(member)
.fetch();
DTO의 생성자에 @QueryProjection을 선언하고, 컴파일을 하면 QMemberDTO 클래스가 생성이 됩니다.
그리고 Projection시에 해당 Q클래스를 이용하여 프로젝션을 수행하면 됩니다.