Open
Description
QueryProjection vs Projections.constructor vs Projections.fields 비교 정리
Querydsl에서 DTO를 생성하는 세 가지 방법, QueryProjection, Projections.constructor, Projections.fields의 특징과 차이점을 비교하여 정리합니다.
1. QueryProjection
@QueryProjection 애노테이션을 사용하여 DTO 클래스에 대해 Querydsl의 Q클래스를 생성하고, 이를 통해 DTO 객체를 생성하는 방식입니다. 생성된 QDto 클래스를 사용하여 데이터를 매핑합니다.
특징
- 타입 체크: 컴파일 타임에 필드 타입과 개수를 체크.
- Querydsl 의존성: DTO가 Querydsl에 종속됩니다.
- 설정 복잡도: APT 플러그인을 통한 코드 생성 필요.
장점
- 컴파일 시 타입 안정성을 제공합니다.
- DTO 필드 변경 시 컴파일러가 오류를 감지합니다.
단점
- Querydsl 의존성 때문에 DTO가 독립적으로 사용하기 어렵습니다.
- APT 설정이 필요합니다.
코드 예제
@Data
@QueryProjection
public class MyDto {
private String name;
private int age;
}
List<MyDto> result = queryFactory
.select(new QMyDto(member.name, member.age))
.from(member)
.fetch();
2. Projections.constructor
DTO의 생성자를 호출하여 데이터를 매핑하는 방식입니다.
특징
- 타입 체크: 런타임에 타입과 필드 개수를 확인합니다.
- Querydsl 독립성: DTO는 Querydsl에 종속되지 않습니다.
- 설정 복잡도: 별도 설정이 필요하지 않습니다.
장점
Querydsl에 종속되지 않아 재사용성이 높습니다.
설정이 간단하며 순수 POJO 설계가 가능합니다.
단점
필드 개수나 타입이 맞지 않을 경우 런타임 오류가 발생할 수 있습니다.
생성자 매핑이 복잡해질 수 있습니다.
코드 예제
public class MyDto {
private String name;
private int age;
public MyDto(String name, int age) {
this.name = name;
this.age = age;
}
}
List<MyDto> result = queryFactory
.select(Projections.constructor(MyDto.class, member.name, member.age))
.from(member)
.fetch();
3. Projections.fields
DTO의 필드 이름을 기준으로 데이터를 매핑하는 방식입니다.
특징
- 타입 체크: 런타임에 필드 이름과 타입을 확인합니다.
- Querydsl 독립성: DTO는 Querydsl에 종속되지 않습니다.
- 필드 이름 기반 매핑: 필드 이름이 동일해야 자동으로 매핑됩니다.
장점
Querydsl 의존성이 없으며, 필드 이름이 같을 경우 간단히 매핑할 수 있습니다.
일부 필드만 매핑할 수 있습니다.
단점
DTO에 기본 생성자와 Setter가 필요합니다.
필드 이름이 다를 경우 명시적으로 매핑해야 합니다.
코드 예제
public class MyDto {
private String name;
private int age;
public MyDto() {}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
List<MyDto> result = queryFactory
.select(Projections.fields(MyDto.class, member.name.as("name"), member.age.as("age")))
.from(member)
.fetch();