2014-11-14 17 views
4

我們有一個項目,我們需要延遲加載一個實體的集合,但在某些情況下,我們需要它們急切地加載。我們已經爲我們的實體添加了一個@NamedEntityGraph註釋。在我們的倉庫方法中,我們添加一個「javax.persistence.loadgraph」提示,以便加載所述註釋中定義的4個屬性。當我們調用這個查詢時,Hibernate會拋出org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bagsNamedEntityGraph - JPA/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); 
} 

爲什麼是這對實體層面渴望回遷工作的任何提示,但不能與動態的實體圖形?

回答

5

我敢打賭,你認爲正在工作的渴望提取,實際上是工作不正確。

如果您渴望獲取多個「bag」(允許重複的unorder集合),則用於執行渴望獲取(左外部聯接)的sql將爲聯合關聯返回多個結果,如SO answer所述。因此,當你有多於一個List渴望提取時,休眠不會拋出org.hibernate.loader.MultipleBagFetchException由於上述原因,它不會返回準確的結果。

但是,當你給查詢實體圖提示時,hibernate會(正確)抱怨。 Hibernate developer, Emmanuel Bernard, addresses the reasons for this exception to be thrown

預先抓取本身不是問題,在一個SQL查詢中使用多個連接是。它不僅限於靜態獲取策略;它從來沒有被支持(財產),因爲它在概念上是不可能的。

Emmanuel goes on to say in a different JIRA comment的是,

最「非索引」列表或原料收集的用途是錯誤的,應該是語義套。

所以底線,爲了得到多渴望獲取你想要的工作:

  • 使用Set,而不是List
  • 堅持使用JPA 2的@OrderColumn註解List指數,
  • 如果一切都失敗,則回退到Hibernate特定的提取註釋(FetchMode.SELECTFetchMode.SUBSELECT

編輯

相關:

相關問題