Hibernate不允许获取多个bag,因为这会生成一个
笛卡尔积,对于无序列表,在Hibernate术语中称为
baggs,即使底层集合没有这些重复行,这也会导致重复条目。因此,当编译JPQL查询时,Hibernate会简单地防止出现这种情况。
现在,你会发现很多答案、博客文章、视频或其他资源告诉你要使用
Set
而不是
List
来处理你的集合。
那是可怕的建议。不要这样做!
使用
Sets
代替
Lists
将使
MultipleBagFetchException
消失,但笛卡尔积仍然存在。
正确的解决方法
不要在单个JPQL或Criteria API查询中使用多个
JOIN FETCH
:
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
最多获取一个集合,就可以避免笛卡尔积问题。通过使用多个查询,您将避免笛卡尔积,因为除第一个集合以外的任何其他集合都是使用辅助查询获取的。
@IndexColumn
已被弃用(目前使用的是 Hibernate 5.2.4.Final 版本)。 - JRSofty@OrderColumn
自 JPA 2.0 起。 - qwazer