인프런 커뮤니티 질문&답변

자프링님의 프로필 이미지
자프링

작성한 질문수

실전! Querydsl

DTO가 DTO를 가지고 있을 때의 Projections.bean() 혹은 @QueryProjection 사용에 대하여

해결된 질문

작성

·

421

0

안녕하세요 영한님

공부한 내용을 복습할겸 호출한 외부 api의 데이터를 Projections.bean() 혹은 @QueryProjection을 이용하여 DTO로 바로 조회하여 저장하는 연습을 하고 있었습니다.

DTO가 일반적인 객체타입이나 원시타입만 가지고 있었을 때에는 큰 상관이 없었으나 DTO가 DTO를 내부적으로 또 가지고 있으니 위의 방법으로는 오류가 발생하였습니다.

DTO안에 DTO가 포함된 관계성은 api 제공 사이트측에서 정한것이라 이를 수정하지는 못했습니다.

리포지토리와 2개의 DTO의 코드는 다음과 같습니다.

@NoArgsConstructor
@Getter @Setter
public class MatchDTO {

    private InfoDTO info;

    @QueryProjection
    public MatchDTO(InfoDTO info) {
        this.info = info;
    }
}
@Getter @Setter
public class InfoDTO {

    private Long gameDuration;

    private String gameMode;

    private List<ParticipantDTO> participants;
}
public class MatchQueryRepositoryImpl implements MatchQueryRepository {

    private final EntityManager em;
    private final JPAQueryFactory query;

    public MatchQueryRepositoryImpl(EntityManager em) {
        this.em = em;
        this.query = new JPAQueryFactory(em);
    }

    @Override
    public Page<MatchDTO> search(MatchSearchCond searchCond, Pageable pageable) {

        List<MatchDTO> content = query
                .select(new QMatchDTO(match.info))
                .from(match)
                .where(gameDurationLoe(searchCond.getGameDuration()))
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetch();

        return new PageImpl<>(content);
    }

    private BooleanExpression gameDurationLoe(Long gameDuration) {
        return gameDuration != null ? match.info.gameDuration.loe(gameDuration) : null;
    }
}

이렇게 코드를 설정하면 다음과 같은 컴파일 오류가 query.select()절에서 발생하였습니다.

Required type: Expression<? extends practice.secondapi.dto.match.InfoDTO>

Provided: QInfo

 

엔티티가 Q객체로 바뀌는 과정에서 타입 불일치가 일어난 듯 싶은데 구체적인 해결책은 잘 모르겠습니다 ㅠㅠ

코드에 넣지는 않았지만 심지어 InfoDTO는 ParticipantDTO를 리스트로 가지고 있기도 해서... 어떻게 야매로 해결한다해도 또 같은 문제가 발생할 것 같아서 근본적인 원인과 해결책이 궁금합니다!

답변 2

1

안녕하세요. 자프링님, 공식 서포터즈 코즈위버입니다.

아래 답변하신 것처럼 matchDTO로 받아 이를 반복문에서 변환하여도 괜찮습니다.

@QueryProjection 을 사용하기 위해선 Q클래스가 생성되어있어야 합니다.

그래서 처음 질문글과 같이 select 에서 Info 로 바로 받기 위해선 InfoDTO 에도 @QueryProjection 생성자를 만들고, Q클래스를 한번 생성해주어야 합니다.

감사합니다.


자프링님의 프로필 이미지
자프링
질문자

감사합니다!!!!

0

자프링님의 프로필 이미지
자프링
질문자

일단 해결한 방법은 그냥 query.selectFrom(match)로 match 엔티티의 리스트를 가져오고 이를 반복문을 통해서 matchDTO로 변환, matchDTO 리스트에 추가한후 반환하는 것인데 뭔가 일을 돌아돌아하는 느낌이라 찜찜하네요..

자프링님의 프로필 이미지
자프링

작성한 질문수

질문하기