gpt4 book ai didi

java - NamedEntityGraph - JPA/Hibernate 抛出 org.hibernate.loader.MultipleBagFetchException : cannot simultaneously fetch multiple bags

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:16:09 26 4
gpt4 key购买 nike

我们有一个项目需要延迟加载实体的集合,但在某些情况下我们需要急切加载它们。我们为我们的实体添加了一个 @NamedEntityGraph 注释。在我们的存储库方法中,我们添加了一个“javax.persistence.loadgraph”提示以急切地加载在所述注释中定义的 4 个属性。当我们调用该查询时,Hibernate 抛出 org.hibernate.loader.MultipleBagFetchException: cannot simultaneous fetch multiple bags

有趣的是,当我将所有这些集合重新定义为急切获取时,Hibernate 确实会急切获取它们,而不会出现 MultipleBagFetchException。

这里是提炼代码。实体:

@Entity
@NamedEntityGraph(name = "Post.Full", attributeNodes = {
@NamedAttributeNode("comments"),
@NamedAttributeNode("plusoners"),
@NamedAttributeNode("sharedWith")
}
)
public class Post {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "postId")
private List<Comment> comments;

@ElementCollection
@CollectionTable(name="post_plusoners")
private List<PostRelatedPerson> plusoners;

@ElementCollection
@CollectionTable(name="post_shared_with")
private List<PostRelatedPerson> sharedWith;

}

查询方法(全部挤在一起以使其可发布):

@Override
public Page<Post> findFullPosts(Specification<Post> spec, Pageable pageable) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Post> query = builder.createQuery(Post.class);
Root<Post> post = query.from(Post.class);
Predicate postsPredicate = spec.toPredicate(post, query, builder);
query.where(postsPredicate);

EntityGraph<?> entityGraph = entityManager.createEntityGraph("PlusPost.Full");

TypedQuery<GooglePlusFullPost> typedQuery = entityManager.createQuery(query);
typedQuery.setHint("javax.persistence.loadgraph", entityGraph);

query.setFirstResult(pageable.getOffset());
query.setMaxResults(pageable.getPageSize());

Long total = QueryUtils.executeCountQuery(getPostCountQuery(specification));

List<P> resultList = total > pageable.getOffset() ? query.getResultList() : Collections.<P>emptyList();
return new PageImpl<P>(resultList, pageable, total);
}

关于为什么这适用于实体级别的预取,但不适用于动态实体图,有什么提示吗?

最佳答案

我敢打赌,您认为有效的急切获取实际上工作不正常。

当您渴望获取多个“包”(允许重复的无序集合)时,用于执行渴望获取(左外连接)的 sql 将为连接的关联返回多个结果,如此 SO answer 所述。 .因此,当您急切地获取多个 List 时,hibernate 不会抛出 org.hibernate.loader.MultipleBagFetchException,但由于上述原因,它不会返回准确的结果。

但是,当您为查询提供实体图提示时,hibernate 会(正确地)提示。 Hibernate developer, Emmanuel Bernard, addresses the reasons for this exception to be thrown :

eager fetching is not the problem per se, using multiple joins in one SQL query is. It's not limited to the static fetching strategy; it has never been supported (property), because it's conceptually not possible.

Emmanuel goes on to say in a different JIRA comment那个,

most uses of "non-indexed" List or raw Collection are erroneous and should semantically be Sets.

所以最重要的是,为了让多个急切的抓取按照你的意愿工作:

  • 使用 Set 而不是 List
  • 使用 JPA 2 的 @OrderColumn 注释保留 List 索引,
  • 如果一切都失败了,回退到 Hibernate 特定的提取注释(FetchMode.SELECTFetchMode.SUBSELECT)

编辑

相关:

关于java - NamedEntityGraph - JPA/Hibernate 抛出 org.hibernate.loader.MultipleBagFetchException : cannot simultaneously fetch multiple bags,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26934011/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com