java – NamedEntityGraph – JPA / Hibernate抛出org.hibernate.loader.MultipleBagFetchException:无法同时获取多个包

前端之家收集整理的这篇文章主要介绍了java – NamedEntityGraph – JPA / Hibernate抛出org.hibernate.loader.MultipleBagFetchException:无法同时获取多个包前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我们有一个项目,我们需要懒惰地加载一个实体的集合,但在某些情况下我们需要它们急切地加载它们.我们在实体中添加了@NamedEntityGraph注释.在我们的存储库方法中,我们添加了一个“ javax.persistence.loadgraph”提示,以急切地加载在所述注释中定义的4个属性.当我们调用查询时,Hibernate会抛出org.hibernate.loader.MultipleBagFetchException:无法同时获取多个包.

有趣的是,当我将所有这些集合重新定义为急切获取时,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”(一个允许重复的unorder集合)时,用于执行eager fetch(左外连接)的sql将返回连接关联的多个结果,如此SO answer所解释的那样.所以虽然hibernate没有抛出org.hibernate.loader.MultipleBagFetchException当你有多个List急切地获取时,由于上面给出的原因,它不会返回准确的结果.

但是,当你给查询提供实体图提示时,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.SELECT或FetchMode.SUBSELECT)

编辑

有关:

> https://stackoverflow.com/a/17567590/225217
> https://stackoverflow.com/a/24676806/225217

猜你在找的Java相关文章