加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – NamedEntityGraph – JPA / Hibernate抛出org.hibernate

发布时间:2020-12-14 06:04:21 所属栏目:Java 来源:网络整理
导读:我们有一个项目,我们需要懒惰地加载一个实体的集合,但在某些情况下我们需要它们急切地加载它们.我们在实体中添加了@NamedEntityGraph注释.在我们的存储库方法中,我们添加了一个“ javax.persistence.loadgraph”提示,以急切地加载在所述注释中定义的4个属性.
我们有一个项目,我们需要懒惰地加载一个实体的集合,但在某些情况下我们需要它们急切地加载它们.我们在实体中添加了@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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读