[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개의 댓글