有趣的是,当我将所有这些集合重新定义为急切获取时,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