我们有一个项目,需要延迟加载实体的集合,但是在某些情况下,我们需要热切地加载它们。我们已经@NamedEntityGraph为实体添加了注释。在我们的存储库方法中,我们添加了一个“ javax.persistence.loadgraph”提示来热切加载上述注释中定义的4个属性。当我们调用该查询时,Hibernate抛出org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags。
@NamedEntityGraph
org.hibernate.loader.MultipleBagFetchException: cannot simultaneously 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); }
有什么暗示为什么这与在实体级别进行热切获取而不是在动态实体图上起作用有关?
我敢打赌,您认为工作正常,实际工作不正确的渴望。
当您渴望获取多个“ bag”(允许重复的无序集合)时,用于执行渴望获取(左外部联接)的sql将为联接的关联返回多个结果,如该SO答案所述。因此,org.hibernate.loader.MultipleBagFetchException当您List渴望获取多个时,hibernate不会抛出,但由于上述原因,它不会返回准确的结果。
org.hibernate.loader.MultipleBagFetchException
List
但是,当您向查询提供实体图提示时,hibernate将(正确地)抱怨。 hibernate开发人员Emmanuel Bernard解决了抛出此异常的原因:
渴望获取本身并不是问题,而是在一个SQL查询中使用多个联接。它不仅仅限于静态获取策略。它从未得到支持(属性),因为从概念上讲是不可能的。
伊曼纽尔在JIRA的另一则评论中说:
“非索引”列表或原始Collection的大多数用法是错误的,在语义上应为Set。
因此,最重要的是,为了使多个热切的获取工作如您所愿:
Set
@OrderColumn
FetchMode.SELECT
FetchMode.SUBSELECT