Projections 의 객체 생성방법 3가지

By | 2022년 7월 25일
Table of Content

Projections 의 객체 생성방법 3가지

Projections 사용법에 대해 오해를 불러올 수 있다는 의견이 있어 문서 추가작성합니다.

@QueryProjection 을 이용한 객체생성

생성되는 QClass 에 있는 생성자를 이용하는 방식입니다.

기존 객체가 생성자를 이용해 생성되고 있었다면 선택의 여지는 없고,
이방법으로만 생성해야 합니다.

현재 시점에서는 어떤 방법을 사용한다고 해도 상관없을 수 있지만,
추후에 생성자에 어떤 로직이 추가될지 알수 없으므로,
선택의 여지가 없습니다.

@Getter
@Setter
@NoArgsConstructor
public class UserGroupByDto {

    private String username;
    private Long count;

    @QueryProjection
    public UserGroupByDto(String username, Long count) {
        this.username = username;
        this.count = count;
    }
}
    public List<UserGroupByDto> groupBy() {

        return jpaQueryFactory
                .select(new QUserGroupByDto(
                                user.username
                                , user.count().as("count")
                        )
                )
                .from(user)
                .groupBy(user.username)
                .orderBy(user.username.asc())
                .fetch();
    }

@Setter 를 이용한 객체생성

@Setter 를 이용해 객체를 생성합니다.

생성자를 private 으로 지정해 차후에도,
생성자를 추가하지 못하게 하면 더 안전한 코드가 됩니다.

@Getter
@Setter
@NoArgsConstructor
public class UserGroupByDto {

    private String username;
    private Long count;

    private UserGroupByDto(String username, Long count) {
        // Projections 을 이용해 객체 생성할 것
        throw new RuntimeException();
    }
}
    public List<UserGroupByDto> groupBy() {

        return jpaQueryFactory
                .select(
                        Projections.bean(
                                UserGroupByDto.class
                                , user.username
                                , user.count().as("count")
                        )
                )
                .from(user)
                .groupBy(user.username)
                .orderBy(user.username.asc())
                .fetch();
    }

fields 를 이용한 객체생성

@Setter 를 생성하지 않고 객체의 데이타를 직접 입력합니다.
불필요할 가능성이 높은 @Setter 추가하지 않아도 된다는 장점이 있습니다.

하지만 객체의 은닉성 원칙을 해치면서 얻어내는 결과라는 점에서 개인적으로는 선호하지 않습니다.
(일종의 편법으로 java 가 언어 레벨에서 막아버릴 수도 있고…
개인적으로는 막혔으면 합니다.)

@Getter
@NoArgsConstructor
public class UserGroupByDto {

    private String username;
    private Long count;

    private UserGroupByDto(String username, Long count) {
        // Projections 을 이용해 객체 생성할 것
        throw new RuntimeException();
    }
}
    public List<UserGroupByDto> groupBy() {

        return jpaQueryFactory
                .select(
                        Projections.fields(
                                UserGroupByDto.class
                                , user.username
                                , user.count().as("count")
                        )
                )
                .from(user)
                .groupBy(user.username)
                .orderBy(user.username.asc())
                .fetch();
    }

답글 남기기