[QueryDSL] 에러 - query specified join fetching, but the owner of the fetched association was not present in the select list

DragonTiger·2023년 4월 18일
0

에러 로그

에러 코드

 public IvcValidationResponseDto findByInvitedCode(String inviteCode) {
        IvcValidationResponseDto ivcValidationResponseDto = jpaQueryFactory.select(
                        new QIvcValidationResponseDto(
                                qInvited.seq,
                                qInvited.createdDate,
                                qInvited.modifiedDate,
                                qInvited.paymentStatus,
                                qMember.nickname
                        )
                )
                .from(qInvited)
                .innerJoin(qInvited.member, qMember)
                .fetchJoin()
                .where(
                        qInvited.invitedCode.eq(inviteCode)
                )
                .fetchOne();

        return ivcValidationResponseDto;
    }

위 코드를 보면 @QueryProjection 을 이용하여 만든 qclass DTO 를 조회하는중이다.
엔티티를 조회하는게 아니고 dto 를 조회하는데 fetch join 을 쓰는것이 문제였던것이다.
fetch join 을 사용하는 이유는 엔티티 상태에서 엔티티 그래프를 참조하기 위해서 사용하는 것이라고한다.
따라서 엔티티가 아닌 DTO 상태로 조회하는 것은 불가능하다고한다.
그렇다면 해결법은 무엇이냐?
순수 join 을 사용하면 깔끔하게 동작한다.
참조 링크

해결책

 public IvcValidationResponseDto findByInvitedCode(String inviteCode) {
        IvcValidationResponseDto ivcValidationResponseDto = jpaQueryFactory.select(
                        new QIvcValidationResponseDto(
                                qInvited.seq,
                                qInvited.createdDate,
                                qInvited.modifiedDate,
                                qInvited.paymentStatus,
                                qMember.nickname
                        )
                )
                .from(qInvited)
                .innerJoin(qInvited.member, qMember)
                .where(
                        qInvited.invitedCode.eq(inviteCode)
                )
                .fetchOne();

        return ivcValidationResponseDto;
    }

고민해야할점

  • 일반 Join : join 조건을 제외하고 실제 질의하는 대상 Entity에 대한 컬럼만 SELECT
  • Fetch Join : 실제 질의하는 대상 Entity와 Fetch join이 걸려있는 Entity를 포함한 모든 컬럼 SELECT

일반적인 join 은 가져오지 않은 필드에 대해선 영속성에 관여하지 않는다는것이다.
가져오지않은 필드를 쓰려면 추가적인 쿼리가 발생할것이며 n+1 문제로 성능저하로 이어질것이다.

실제 필요한 컬럼들만 조회해야 할때에는 일반적인 조인이 효과적일것이며,
연관관계가 걸려있는 Entity의 정보도 같이 사용해야할때에는 fetch join이 맞는판단 인거같다.

profile
take the bull by the horns

0개의 댓글

Powered by GraphCDN, the GraphQL CDN