-
Querydsl - DTO로 조회하기Spring/Querydsl 2022. 3. 25. 12:15728x90반응형
순수 JPA에서의 DTO 조회
- new 명령어 사용해야 한다.
- DTO의 package 이름을 다 적어줘야하는 불편함이 있다.
- 생성자 방식만 지원한다.
List<MemberDto> result = em.createQuery( "select new study.querydsl.dto.MemberDto(m.username, m.age) " + "from Member m", MemberDto.class) .getResultList();
위와 같은 순수 JPA에서의 DTO 조회 시 사용하기 불편했던 것들을 Querydsl에서 해결해준다.
DTO로 조회하기
- 프로퍼티 접근 - setter
- 필드 직접 접근
- 생성자 사용
- @QueryProjection
프로퍼티 접근 - setter
- Projections.bean(class, {field, ...}) 사용
- DTO의 getterm setter가 필요하다.
@Test @DisplayName("DTO 조회 - 프로퍼티 접근") public void dtoProperty() { 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); } }
/* select member1.username, member1.age from Member member1 */ select member0_.username as col_0_0_, member0_.age as col_1_0_ from member member0_
memberDto = MemberDto(username=member1, age=10) memberDto = MemberDto(username=member2, age=20) memberDto = MemberDto(username=member3, age=30) memberDto = MemberDto(username=member4, age=40)
Tuple을 사용하지 않고 DTO를 이용하여 필요한 정보만 가져온 것을 볼 수 있다.
필드 직접 접근
- Projections.fields(class, {field, ...}) 사용
- DTO의 getter, setter가 없어도 사용 가능
@Test @DisplayName("DTO 조회 - 필드 접근") public void dtoField() { 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); } }
/* select member1.username, member1.age from Member member1 */ select member0_.username as col_0_0_, member0_.age as col_1_0_ from member member0_
memberDto = MemberDto(username=member1, age=10) memberDto = MemberDto(username=member2, age=20) memberDto = MemberDto(username=member3, age=30) memberDto = MemberDto(username=member4, age=40)
필드명이 다른 경우에는 다음과 같이 별칭(alias)를 사용하면 된다. 필드명과 데이터명이 다를 경우 필드에는 null이 들어가니 조심하자.
@Data public class UserDto { private String name; private int age; } List<UserDto> fetch = queryFactory .select(Projections.fields(UserDto.class, member.username.as("name"), // (1) ExpressionUtils.as( // (2) JPAExpressions .select(memberSub.age.max()) .from(memberSub), "age") ) ).from(member) .fetch();
- 프로퍼티나, 필드 접근 생성 방식에서 이름이 다를 때 해결 방안
- (1) : username.as("memberName") : 필드에 별칭 적용
- (2) : ExpressionUtils.as(source, alias) : 필드나 서브 쿼리에 별칭 적용
생성자 사용
- Projections.constructor(class, {field, ...}) 사용
- 필드와 타입이 일치해야 한다.
@Test @DisplayName("DTO 조회 - 생성자 접근") public void dtoConstruct() { List<Member> results = queryFactory .select(Projections.constructor(Member.class, member.username, member.age)) .from(member) .fetch(); for (Member result : results) { System.out.println("result = " + result); } }
/* select member1.username, member1.age from Member member1 */ select member0_.username as col_0_0_, member0_.age as col_1_0_ from member member0_
memberDto = MemberDto(username=member1, age=10) memberDto = MemberDto(username=member2, age=20) memberDto = MemberDto(username=member3, age=30) memberDto = MemberDto(username=member4, age=40)
@QueryProjection
- 생성자에 @QueryProjection을 사용하면 Q-Type이 생성된다.
- 컴파일러로 타입을 체크할 수 있어 가장 안전한 방법(ctrl+p 로 파라미터 확인 가능)
- DTO까지 Q 파일을 생성해야하는 단점
- DTO가 Querydsl에 대한 의존성을 갖게 된다.
@Data public class MemberDto { private String username; private int age; public MemberDto() { } @QueryProjection // (1) public MemberDto(String username, int age) { this.username = username; this.age = age; } }
- (1) : QMemberDto 만들어 주는 어노테이션
@Test @DisplayName("QueryProjection") public void queryProjection() { List<MemberDto> results = queryFactory .select(new QMemberDto(member.username, member.age)) .from(member) .fetch(); for (MemberDto result : results) { System.out.println("result = " + result); } }
/* select member1.username, member1.age from Member member1 */ select member0_.username as col_0_0_, member0_.age as col_1_0_ from member member0_
result = MemberDto(username=member1, age=10) result = MemberDto(username=member2, age=20) result = MemberDto(username=member3, age=30) result = MemberDto(username=member4, age=40)
728x90반응형'Spring > Querydsl' 카테고리의 다른 글
Querydsl - where절을 이용한 동적 쿼리 (0) 2022.03.25 Querydsl - BooleanBuilder 이용한 동적 쿼리 (0) 2022.03.25 Querydsl - 프로젝션에 따른 결과 반환 (0) 2022.03.25 Querydsl - Querydsl 기본 문법 (0) 2022.03.23 Querydsl - 설정 및 검증 (0) 2022.03.22