본문 바로가기
공부/QueryDSL

QueryDSL 공부하기 - 4 ( DTO조회 )

by 고구밍 2022. 5. 13.

 

QueryDSL 조회방법 3가지!

 

1. 결과가 하나일 때 -> 바로 지정하기 -> List<String>

@Test
public void simpleProjection() {
    List<String> result = queryFactory
            .select(member.username)
            .from(member)
            .fetch();

    for (String s : result) {
        System.out.println("result = " + result);
    }
}

 

 

 

2. 결과가 둘 이상일 경우 Tuple을 사용 -> List<Tuple>

* 레포지토리 안에서만 사용하기 -> 다른곳에서 사용할려면 dto를 통해서 담아서 보내기

 

@Test
public void selectSubQuery() {

    QMember memberSub = new QMember("memberSub");

    List<Tuple> result = queryFactory
            .select(member.username,
                    select(memberSub.age.avg())
                            .from(memberSub))
            .from(member)
            .fetch();

    for (Tuple tuple : result) {
        System.out.println("tuple = " + tuple);
    }

}

 

 

 

3. Dto 조회

 

ⓐ 순수 JPA -> new 오퍼레이션(폴더주소)

 

@Test
public void findDtoByJPQL(){
    List<MemberDto> result = em.createQuery("select new study.querydsl.dto.MemberDto(m.username, m.age) from Member m", MemberDto.class)
            .getResultList();
    for (MemberDto memberDto : result) {
        System.out.println("memberDto = " + memberDto);
    }
}

 

 

ⓑ QueryDSL 3가지 방법!

 

ㄱ. 프로퍼티 접근 - Setter

@Test
public 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
public 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);
    }
}

 

 

ㄷ. 생성자 사용

@Test
public void findUserDto() {
    QMember memberSub = new QMember("memberSub");
    List<UserDto> result = queryFactory
            .select(Projections.fields(UserDto.class,
                    ExpressionUtils.as(member.username, "name"),

                    ExpressionUtils.as(JPAExpressions
                            .select(memberSub.age.max())
                                .from(memberSub), "age")
            ))
            .from(member)
            .fetch();

    for (UserDto userDto : result){
        System.out.println("userDto = " + userDto);
    }
}
package study.querydsl.dto;

import lombok.Data;

@Data
public class UserDto {

    private String name;
    private int age;

    public UserDto() {
    }

    public UserDto(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

 

 

* @QuryProjection 

Dto도 Q파일로생성

(Gradle -> orther -> compileQuerydsl을 눌러서 dto에대한 Q파일생성 - 어노테이션을 사용해야 함)

 

-> 다른 방법들에 비해서, 빼먹은 내용을 검사해 주기때문에 가장 안전함

단점)

1. Q파일을 생성해야 됨

2. DTO에 @QueryProjection을 넣어줘야 함

-> Dto자체가 쿼리 DSL에 의존성을 갖게됨 -> 라이브러리를 제거할 때 영향을 받음

순수하지 않음 : 단순히 어노테이션을 제거하면 되지만, 전체 서비스에서 사용되다보니 서비스에 영향을 받게 됨

 

package study.querydsl.dto;

import com.querydsl.core.annotations.QueryProjection;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class MemberDto {


    private String username;
    private  int age;


    @QueryProjection
    public MemberDto(String username, int age) {
        this.username = username;
        this.age = age;
    }
}
@Test
public void findDtoByQueryProjection() {
    List<MemberDto> result = queryFactory
            .select(new QMemberDto(member.username, member.age))
            .from(member)
            .fetch();

    for (MemberDto memberDto : result) {
        System.out.println("memberDto = " + memberDto);
    }
}

'공부 > QueryDSL' 카테고리의 다른 글

QueryDSL 공부하기 - 3  (0) 2022.05.11
QueryDSL 공부하기 - 2  (0) 2022.05.11
QueryDSL 공부하기 - 1  (0) 2022.05.10