MemberDTO
package study.querydsl.dto;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
public class MemberDTO {
private String username;
private int age;
public MemberDTO(String username, int age) {
this.username = username;
this.age = age;
}
}
JPQL에서 DTO로 조회하는 방법은 다음과 같다.
@Test
public void findDtoByJPQL(){
//아래와 같이 생성자를 사용하는 것과 같은 문법으로 진행되는데, 매우 길다...
//쉼표 뒤에는 DTO의 클래스타입을 넣어주고, select 뒤에 새로운 생성자로 객체를 생성하듯 넣어준다.
//그러면 리턴 타입이 DTO로 나오게 된다.
List<MemberDTO> resultList = em.createQuery("select new study.querydsl.dto.MemberDTO(m.username,m.age) from Member m", MemberDTO.class)
.getResultList();
for (MemberDTO memberDTO : resultList) {
System.out.println("memberDTO = " + memberDTO);
}
}
이 테스트의 실행 결과는 다음과 같다.
memberDTO = MemberDTO(username=member1, age=10)
memberDTO = MemberDTO(username=member2, age=20)
memberDTO = MemberDTO(username=member3, age=30)
memberDTO = MemberDTO(username=member4, age=40)
위와 같이 DTO 타입으로 나오게 된다
위를 개선한 방식이 queryDsl에서 제공하는 방법이다.
총 세가지 방식이 있는데, setter 사용방식, fields 사용방식, 생성자 사용방식이 있다.
@Test
public void findDtoBySetter() throws Exception{
//given
List<MemberDTO> fetch = queryFactory.select(Projections.
bean(MemberDTO.class,
member.username, member.age))
.from(member)
.fetch();
for (MemberDTO memberDTO : fetch) {
System.out.println("memberDTO = " + memberDTO);
}
//when
//then
}
@Test
public void findDtoByFields() throws Exception{
//given
List<MemberDTO> fetch = queryFactory.select(Projections.
fields(MemberDTO.class,
member.username, member.age))
.from(member)
.fetch();
for (MemberDTO memberDTO : fetch) {
System.out.println("memberDTO = " + memberDTO);
}
//when
//then
}
@Test
public void findDtoByConstructor() throws Exception{
//given
List<MemberDTO> fetch = queryFactory.select(Projections.
constructor(MemberDTO.class,
member.username, member.age))
.from(member)
.fetch();
for (MemberDTO memberDTO : fetch) {
System.out.println("memberDTO = " + memberDTO);
}
//when
//then
}
setter방식이나, fields 방식의 경우, DTO와 Qtype에 있는 변수의 이름이 같으면 상관이 없지만, 다른 경우에는 값이 들어가지 않는 경우가 발생한다.
아래는 그 경우를 Test코드로 작성한 것이다.
QEntity의 변수명과 DTO의 변수명이 다를 때 Setter방식의 동작
UserDTO
package study.querydsl.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UserDTO {
private String name;//
private int age;
}
@Test
public void findUserDTO() throws Exception{
//given
List<UserDTO> fetch = queryFactory.select(Projections.bean(UserDTO.class,
member.username, member.age))
.from(member)
.fetch();
for (UserDTO userDTO : fetch) {
System.out.println("UserDTO = " + userDTO);
}
//when
//then
}
//name에 모두 null이 들어간 것을 볼 수 있다.
UserDTO = UserDTO(name=null, age=10)
UserDTO = UserDTO(name=null, age=20)
UserDTO = UserDTO(name=null, age=30)
UserDTO = UserDTO(name=null, age=40)
위와 같은 방식의 해결 방법은 다음과 같다.
as를 통한 해결방법
@Test
public void findUserDTOAs() throws Exception{
//given
List<UserDTO> fetch = queryFactory.select(Projections.
bean(UserDTO.class,
//이곳에 as 를 붙이고 받고싶은 DTO의 변수명을 입력
//그럼 변수가 자동으로 DTO의 변수와 매칭이됨
member.username.as("name"), member.age))
.from(member)
.fetch();
for (UserDTO userDTO : fetch) {
System.out.println("UserDTO = " + userDTO);
}
}
UserDTO = UserDTO(name=member1, age=10)
UserDTO = UserDTO(name=member2, age=20)
UserDTO = UserDTO(name=member3, age=30)
UserDTO = UserDTO(name=member4, age=40)
위와같이 결과가 나오게 된다.
Uploaded by N2T