[JPA] MultipleBagException

charco·2021년 8월 6일
0

!ERROR!

목록 보기
12/17
post-custom-banner

다음과 같은 JPQL 을 날리려고 했는데 예외가 발생했다.

return em.createQuery("select m from Member m" +
                " join fetch m.boards b" +
                " join fetch m.replies r", Member.class)
                .getResultList().get(0);

Member 는 boards 와 replies 를 모두 OneToMany 관계로 갖고있다.

원인은 여러개의 컬렉션타입 엔티티를 동시에 fetch 한 것이었다.
그래서 MultipleBagExcpetion 이 발생했다.

왜 안될까.. 생각해보자

일단 하이버네이트가 날려줄 쿼리에 대해 생각해보자.

대충

select * from member m 
    inner join board b on b.member_id = m.member_id
    inner join reply r on r.member_id = m.member_id
    where m.member_id = ?

이것은 카테시안 곱이 발생한다. 그래서 하이버네이트가 제약을 건 것이다.

스택오버플로우에 검색을 해봤는데
List 를 Set으로 바꾸면 된다는 답변들이 있었다.

그런데 그 답변들에 대해 최악의 해결책이라고 말하는 답변도 있었다.
Set으로 바꿔도 DB쪽에서는 카테시안곱이 그대로 발생한다는 것이었다.

그래서 그 답변은 다른 해결책을 줬는데
컬렉션에따라 각각 쿼리를 날려주라는 것이었다.

List<Post> posts = entityManager
.createQuery(
    "select distinct p " +
    "from Post p " +
    "left join fetch p.comments " +
    "where p.id between :minId and :maxId ", Post.class)
.setParameter("minId", 1L)
.setParameter("maxId", 50L)
.setHint(QueryHints.PASS_DISTINCT_THROUGH, false)
.getResultList();

posts = entityManager
.createQuery(
    "select distinct p " +
    "from Post p " +
    "left join fetch p.tags t " +
    "where p in :posts ", Post.class)
.setParameter("posts", posts)
.setHint(QueryHints.PASS_DISTINCT_THROUGH, false)
.getResultList();

첫번째 쿼리에서는 distinct 가 반영되지 않을거라서
PASS_DISTINCT_THROUGH 를 false로 지정해줬다고 한다.
이부분에 대해서는 잘 모른다.

일단 먼저 익숙해지는게 우선이기때문에
엔티티를 두개로 나누어 진행해야겠다.

profile
아직 배우는 중입니다
post-custom-banner

0개의 댓글