오봉이와 함께하는 개발 블로그
Querydsl - 프로젝션 결과 반환 (DTO 조회) 본문
728x90
프로젝션과 결과 반환 - DTO 조회
먼저 순수 JPA에서 DTO 조회하는 방법을 보자.
순수 JPA에서 DTO 조회
@Data
public class MemberDto {
private String username;
private int age;
public MemberDto(String username, int age) {
this.username = username;
this.age = age;
}
}
@Test
void findDto() {
List<MemberDto> result = em.createQuery("select new study.querydsl.dto.MemberDto(musername, m.age) " +
"from Member m", MemberDto.class)
.getResultList();
for (MemberDto memberDto : result) {
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)
- 순수 JPA에서 DTO를 조회할 때는 new 명령어를 사용해야 한다.
- DTO의 package이름을 다 적어줘야해서 지저분하다.
- 생성자 방식만 지원한다.
Querydsl 빈 생성(Bean population)
결과를 DTO로 반환할 때 사용하는 방법은 다음 3가지 방법이 있다.
- 프로퍼티 접근
- 필드 직접 접근
- 생성자 사용
프로퍼티 접근 - Setter
com.querydsl.core.types.Projections
를 사용한다.
단, 이 방법을 사용할 때는 DTO에 기본 생성자
, Getter
, Setter
가 있어야 한다.
@Data
public class MemberDto {
// ...............
public MemberDto() {
}
// .........
}
@Test
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);
}
}
필드 직접 접근
@Test
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);
}
}
Getter
, Setter
모두 필요 없고 필드에 값을 다 꽂아서 사용한다.
필드 직접 접근 - 별칭이 다를 때
@Data
public class UserDto {
private String name;
private int age;
}
@Test
void findDtoByFieldAlias() {
QMember memberSub = new QMember("memberSub");
List<UserDto> fetch = 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 : fetch) {
System.out.println("userDto = " + userDto);
}
}
userDto = UserDto(name=member1, age=40) // 원래는 10
userDto = UserDto(name=member2, age=40) // 원래는 20
userDto = UserDto(name=member3, age=40) // 원래는 30
userDto = UserDto(name=member4, age=40)
서브 쿼리의 결과를 별칭에 매칭 시켜서 UserDto
의 age
필드에 주입 시켜 출력한다.
("age"
가 별칭을 지정해줌.)
- 프로퍼티나, 필드 접근 생성 방식에서 이름이 다를 때 해결 방안
- ExpressionUtils.as(source,alias)
- 필드나 서브 쿼리에 별칭 적용
- username.as("memberName")
- 필드에 별칭 적용
생성자 사용
@Test
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);
}
}
이 방법은 MemberDto
에 있는 username
과 Member엔티티
에 있는 username
의 타입이 맞아야 실행 가능한 방법이다.(불러오는 필드의 타입이 모두 일치해야 한다.)
UserDto에 사용
@Data
public class UserDto {
private String name;
private int age;
public UserDto() {
}
public UserDto(String name, int age) {
this.name = name;
this.age = age;
}
}
@Test
void findDtoByConstructor() {
List<UserDto> result = queryFactory
.select(Projections.constructor(UserDto.class,
member.username,
member.age))
.from(member)
.fetch();
for (UserDto userDto : result) {
System.out.println("userDto = " + userDto);
}
}
파라미터가 있는 생성자(public UserDto(String name, int age)
)의 순서에 맞춰서 값이 주입되기 때문에 아래 처럼 member.age
, member.username
순서로 작성하면 안 된다.
@Test
void findDtoByConstructor() {
List<UserDto> result = queryFactory
.select(Projections.constructor(UserDto.class,
member.age,
member.username))
.from(member)
.fetch();
for (UserDto userDto : result) {
System.out.println("userDto = " + userDto);
}
}
인프런 김영한 지식공유자님 강의 : 실전! Querydsl
728x90
'BE > JPA' 카테고리의 다른 글
Querydsl - 동적 쿼리(BooleanBuilder) (0) | 2022.09.18 |
---|---|
Querydsl - 프로젝션 결과 반환 (@QueryProjection) (0) | 2022.09.18 |
Querydsl - 프로젝션 결과 반환 (기본) (0) | 2022.09.18 |
Querydsl - 상수, 문자 더하기 (0) | 2022.09.18 |
Querydsl - Case 문 (0) | 2022.09.18 |
Comments