프로젝트를 진행하면서 조회한 도메인을 Mapstruct 라이브러리를 사용해 DTO로 매핑했었다. 하지만 점점 비즈니스 로직이 복잡해면서 매핑을 위한 코드도 같이 복잡해지다보니 도메인을 거치지 않고 DTO로 반환하는 방법이 있는지 찾아보게 되었다.
그러다 Querydsl로 DTO를 조회하는 방법을 알게 되었고 그 방법에 대해 정리해보려고 한다.
Queyrdsl란?
Querydsl은 JPA와 같은 ORM 프레임워크를 사용할 때 쿼리 작성을 더 편하게 해주는 라이브러리다. Querydsl을 사용하면 동적 쿼리 작성이 가능하다. Querydsl을 사용하면 SQL과 JPA의 복잡한 문법을 피할 수 있으며, 코드 작성이 간결해진다.
Queyrdsl은 동적 쿼리 작성이 가능하며, 도메인 객체를 DTO로 변환하여 반환하는 기능을 제공한다. 이를 통해 DTO와 도메인 객체 사이의 변환 작업을 간소화 할 수 있다.👍
DTO란?
DTO는 Data Transfer Object의 약자로, 데이터 전송을 위한 객체를 의미한다. DTO는 주로 여러 개의 도메인 객체를 하나의 객체로 묶어서 전송할 때 사용된다.
Querydsl은 도메인 객체를 조회할 때 DTO로 변환하여 반환하는 기능을 제공한다. 이를 사용하면 객체와 DTO 사이의 변환이 필요 없어지므로 코드 작성이 간단해진다.
Querydsl을 사용해 DTO 반환 받는 방법
우선 DTO로 변환할 필드를 정의해야한다.
@Data
@NoArgsConstructor
public class MemberDTO {
private String username;
private int age;
public MemberDTO(String username, int age) {
this.username = username;
this.age = age;
}
}
Querydsl의 Projections 클래스를 사용하여 DTO를 반환받을 수 있다.
Projections 클래스는 3가지 방법을 지원한다.
- Setter
- Field
- Constructor
- Constructor + @QueryProjection
Setter 방식
List<MemberDto> memberDtos = queryFactory
.select(Projections.bean(MemberDto.class,
member.username,
member.age))
.from(member)
.fetch();
Field 방식
List<MemberDto> memberDtos = queryFactory
.select(Projections.fields(MemberDto.class,
member.username,
member.age))
.from(member)
.fetch();
Constructor 방식
List<MemberDto> memberDtos = queryFactory
.select(Projections.constructor(MemberDto.class,
member.username,
member.age))
.from(member)
.fetch();
Constructor + @QueryProjection
이 방법은 컴파일러로 타입을 체크할 수 있기 때문에 4가지 방법 중 가장 안전한 방법이다. 단점으로는 DTO에 Querydsl 애너테이션을 넣어야 하기 때문에 필요에 따라 4가지 방법 중 선택하여 사용하면 된다.
@Data
@NoArgsConstructor
public class MemberDTO {
private String username;
private int age;
@QueryProjection
public MemberDTO(String username, int age) {
this.username = username;
this.age = age;
}
}
gradle에서 compileQuerydsl을 실행하여 QMemberDto를 생성한다.
List<MemberDto> memberDtos = queryFactory
.select(new MemberDto(member.username, member.age))
.from(member)
.fetch();
마무리
Querydsl을 사용하여 DTO를 반환 받는 방법에 대해 알아보았다. 이 방법을 다음 프로젝트에 적용해 봐야겠다!
참조
'JPA' 카테고리의 다른 글
JPA - 연관 관계를 위한 불필요한 select 줄이기(getReferenceById()) (0) | 2024.11.18 |
---|---|
Querydsl - Expressions클래스로 select에서 상수 사용하는 법 (1) | 2024.11.14 |
Spring Data JPA - 외래키(Foreign Key)를 복합 기본키(Composite Primary Key)로 사용하기 (1) | 2024.11.08 |
JPA - 하나의 컬럼에 여러 개의 데이터를 저장하기 (0) | 2023.05.08 |
Spring Data JPA - Auditing으로 생성일, 수정일 자동화하는 법 (0) | 2022.12.02 |