[Spring Boot] 2개 이상의 OneToMany & FetchJoin

어디든 배우자·2023년 11월 3일
0

N+1 피하려다 만난놈

원인 - cannot simultaneously fetch multiple bags:

우선, QueryDsl에서 fetchJoin을 사용하면서 N+1을 피하다가 @OneToMany 2개 에다가
fetchJoin을 두 번 사용하다가 만남.
List Collection을 BagType으로 인식함.
그래서 hibernate는 여러 개의 BagType에 대한 fetchJoin을 허용하지 않는다고 함.

문제코드

return queryFactory
                .selectFrom(postInfo)
                .leftJoin(postInfo.postDetailImages).fetchJoin()
                .leftJoin(postInfo.postThumbnailImages).fetchJoin()
                .where(postInfo.postSeq.eq(postSeq))
                .fetchOne();

해결방안 및 과정

List 자료 구조를 Set으로 바꿔봄.
하지만 잘못된 방법이라고 해서 더 찾아보니
Entity가 현재 영속성 처리가 되지 않은 상태에서 set에 데이터를 넣으면
데이터가 사라질 수 있음.
또, 데이터의 수가 확 늘어 난다고 함. 그래서 결국 Set 방법 탈락

fetchJoin 나눠서 들고 오는 방법을 파악! 쿼리가 길어지는 것보다
나누어 쿼리를 호출 할 수 있으니 속도를 개선시킬 여지가 보였음!

해결코드

 	QPostInfo qPostInfo = QPostInfo.postInfo;
    QPostDetailImage qPostDetailImage = QPostDetailImage.postDetailImage;
    QPostThumbnailImage qPostThumbnailImage = QPostThumbnailImage.postThumbnailImage;

    PostInfo postInfo = queryFactory
      	.selectFrom(qPostInfo)
      	.where(qPostInfo.postSeq.eq(postSeq))
      	.distinct()
      	.fetchOne();

	if (postInfo != null) {
      	List<PostDetailImage> postDetailImages = queryFactory
          	.selectFrom(qPostDetailImage)
          	.where(qPostDetailImage.postInfo.postSeq.eq(postSeq))
          	.distinct()
          	.fetch();

      	List<PostThumbnailImage> postThumbnailImages = queryFactory
          	.selectFrom(qPostThumbnailImage)
          	.where(qPostThumbnailImage.postInfo.postSeq.eq(postSeq))
          	.distinct()
          	.fetch();

        postInfo.setPostDetailImages(postDetailImages);
        postInfo.setPostThumbnailImages(postThumbnailImages);
    }

    return postInfo;
이 과정을 MapStruct로 처음 이용해서 변환했습니다. 근데 나름 쉽게 성공해서 패스!
profile
다 흡수하기.

0개의 댓글