Hibernate 不允许获取多个包,因为这会生成笛卡尔积 http://en.wikipedia.org/wiki/Cartesian_product.
现在,您会发现很多答案、博客文章、视频或其他资源告诉您如何使用Set
代替List
为您的收藏。
这是个糟糕的建议!
Using Sets
代替Lists
将使MultipleBagFetchException
消失,但笛卡尔积仍然存在。
正确的修复
而不是使用多个JOIN FETCH
在单个 JPQL 或 Criteria API 查询中:
List<Post> posts = entityManager.createQuery("""
select p
from Post p
left join fetch p.comments
left join fetch p.tags
where p.id between :minId and :maxId
""", Post.class)
.setParameter("minId", 1L)
.setParameter("maxId", 50L)
.getResultList();
您可以执行以下技巧:
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();
只要您使用最多获取一个集合JOIN FETCH
, 你会好起来的。通过使用多个查询,您将避免使用笛卡尔积,因为除了第一个集合之外的任何其他集合都是使用辅助查询获取的。