QueryDSL - 프로젝션과 결과 반환

목차

프로젝션과 결과 반환

프로젝션(Projection) 은 쿼리 결과를 가져올 때 반환할 필드를 지정하는 것

프로젝션 : select 대상 지정

  • 프로젝션 대상이 하나면 타입을 명확하게 지정할 수 있다.
  • 프로젝션 대상이 둘 이상이면 튜플 이나 DTO 로 조회한다.
List<String> result = queryFactory
.select(member.username.concat("_").concat(member.age.stringValue()))
.from(member)
.where(member.username.eq("member1"))
.fetch();

튜플 조회

@Test
public void tupleProjection(){
List<Tuple> result = queryFactory
.select(member.username, member.age)
.from(member)
.fetch();

for (Tuple tuple : result){
String username = tuple.get(member.username);
Integer age = tuple.get(member.age);

System.out.println("username = " + username);
System.out.println("age = " + age);
}
}
/* select
member1.username,
member1.age
from
Member member1 */ select
member0_.username as col_0_0_,
member0_.age as col_1_0_
from
member member0_

DTO 를 이용한 결과 반환

Projections 를 사용하면 쿼리 결과를 DTO 로 변환할 수 있다.

Projections 을 이용한 DTO 반환 방식은 3가지 방법을 지원한다.

  • Setter 를 이용한 방식
  • Field 에 직접 접근하는 방식
  • 생성자를 이용한 방식

Setter 를 활용하는 방법

setter 를 이용한 방식은 Projections.bean 메소드를 이용해 쿼리 결과를 반환하도록 한다.

@Test
public void findDtoBySetter(){
List<MemberDto> result = queryFactory
.select(Projections.bean(MemberDto.class, member.username, member.age))
.from(member)
.fetch();

for (MemberDto memberDto : result) {
System.out.println("memberDto = " + memberDto);
}
}

필드 직접 접근

field 를 이용한 방식은 Projections.fields 메소드를 이용해 쿼리 결과를 반환하도록 한다.

@Test
public void findDtoByField(){
List<MemberDto> result = queryFactory
.select(Projections.fields(MemberDto.class, member.username, member.age))
.from(member)
.fetch();

for (MemberDto memberDto : result) {
System.out.println("memberDto = " + memberDto);
}
}

생성자 사용

생성자를 이용한 방식은 Projections.constructor 메소드를 이용해 쿼리 결과를 반환하도록 한다.

@Test
public void findDtoByConstructor(){
List<MemberDto> result = queryFactory
.select(Projections.constructor(MemberDto.class, member.username, member.age))
.from(member)
.fetch();

for (MemberDto memberDto : result) {
System.out.println("memberDto = " + memberDto);
}
}

DTO 와 Entity 의 Attribute 의 alias 가 서로 다를 경우

@Test
public void findUserDto(){
List<UserDto> result = queryFactory
.select(Projections.fields(UserDto.class, member.username.as("name"), member.age))
.from(member)
.fetch();

for (UserDto userDto : result) {
System.out.println("userDto = " + userDto);
}
}

서브 쿼리에 alias 사용

ExpressionUtils.as

@Test
public void findUserDto(){
QMember memberSub = new QMember("memberSub");

List<UserDto> result = queryFactory
.select(Projections.fields(UserDto.class
, member.username.as("name")
, ExpressionUtils.as(JPAExpressions
.select(memberSub.age.max())
.from(memberSub), "age")))
.from(member)
.fetch();

for (UserDto userDto : result) {
System.out.println("userDto = " + userDto);
}
}
@Test
public void findDtoByConstructor(){
List<MemberDto> result = queryFactory
.select(Projections.constructor(MemberDto.class, member.username, member.age))
.from(member)
.fetch();

for (MemberDto memberDto : result) {
System.out.println("memberDto = " + memberDto);
}
}
Share