@Test // [Property 접근법] : getter를 사용하여 property에 접근하고, setter를 이용하여 값을 삽입
void findDtoBySetter(){
List<MemberDto> results = queryFactory
.select(Projections.bean(MemberDto.class,
member.username,
member.age))
.from(member)
.fetch();
for (MemberDto result : results) {
System.out.println("result = " + result);
}
@Data
public class MemberDto {
private String username;
private int age;
public MemberDto(String username,int age){
this.username = username;
this.age = age;
}
}
JPQL에서 new 연산자를 통해서 바로 Dto로 조회를 하는 기능을 QueryDsl도 제공을 한다.
그런데, 위 코드를 돌리게 되면 아래와 같은 에러가 난다.
즉, 객체를 생성하지 못하는 에러가 발생을 하고 있다.
@Data는 @RequiredConstructor이라는 기능을 지원한다.
그런데 이 에노테이션은 final 키워드가 붙은 키워드에 대해서만 생성자를 만들어 준다.
[기본 생성자]에 대해서는 생성을 해 주지 않는다.
Querydsl에서 new 기능을 사용하기 위해서는 Dto에 [기본 생성자]가 꼭 있어야 한다.
@Data
@NoArgsConstructor // 기본 생성자
public class MemberDto {
private String username;
private int age;
//
//ublic MembberDto()
//{}
public MemberDto(String username,int age){
this.username = username;
this.age = age;
}
}
또 다른 에러의 종류를 살펴 보자.
@Data
public class UserDto {
private String name;
private int age;
}
@Test // [필드 직접 접근] : 이건 getter, setter 없이, 필드에 바로 값을 꽂음.
void findDtoByField(){
List<MemberDto> results = queryFactory
.select(Projections.fields(UserDto.class, // Dto가 UserDto로 바뀜.
member.username, // UserDto에는 username이 없다.
member.age))
.from(member)
.fetch();
UserDto의 필드 중, member."username"과 매칭하는 필드명이 없으므로, null로 들어 간다.
필드명이 불일치할 경우, 아래와 같이 as를 붙여 alias를 붙여 줘야 한다.
@Test
void findUserDto(){
List<UserDto> results = queryFactory
.select(Projections.fields(UserDto.class, // Dto가 MemberDto에서 UserDto로 바뀜.
member.username.[as("name")], // UserDto의 필드에는 [username]이라는 필드명이 없다.(결과를 출력하면, name = [null]로 뜰 것이다.)
member.age))
.from(member)
.fetch();
for (UserDto result : results) {
System.out.println("result = " + result);
}
}
@Test // 서브 쿼리에 alias를 설정하여, UserDto의 필드에 서브쿼리의 결과 값을 삽입 가능하다.
void findUserDtoSubQuery(){
QMember memberSub = new QMember("memberSub");
List<UserDto> results = queryFactory
.select(Projections.fields(UserDto.class,
member.username.as("name"),
//서브 쿼리의 결과를 UserDto의 "name"필드에 삽입
ExpressionUtils
.as(
JPAExpressions
.select(memberSub.age.max())
.from(memberSub),"age") // 서브 쿼리의 결과값의 alias를 "age"로 줘서, UserDto::name에 삽입
))
.from(member)
.fetch();
for (UserDto result : results) {
System.out.println("result = " + result);
}
}
꼭 서브 쿼리가 아니더라도, 사용이 가능하다.
예를 들어, member.username.as("name") == ExpressionUtils.as(member.username, "username")
'CS 잡지식' 카테고리의 다른 글
연관 관계 세팅 TIP!!! (0) | 2023.05.19 |
---|---|
샘플 데이터 입력의 2가지 방법 (0) | 2023.05.19 |
use_sql_comments: true (0) | 2023.05.17 |
Querydsl 사용 템플릿 (0) | 2023.05.17 |
EntityManager에 대한 동시성(concurrency) 문제 (0) | 2023.05.17 |