2014-11-04 28 views
0

我正在使用jpa 2.1 EntityGraphs来修改不同的jpa查询,并且在某些情况下,EntityGraphs无法按预期工作。我正在努力的简单用例是带有子属性查询的jpa实体图

作为父类与单向一对多的书籍子类的关系,我想检索给定书名的作者结果像findAllAuthorsByBookName。

我Author类看起来像这样

@Entity 
@NamedEntityGraph(name = "graph.author.detail", attributeNodes = { 
     @NamedAttributeNode("books") 
}) 
public class Author extends GenericEntity { 

    @OneToMany 
    @JoinColumn(name="author_id") 
    private Set<Book> books = new HashSet<Book>(); 
.... 

书有没有回头参考笔者所以它看起来像这样

@Entity 
public class Book extends GenericEntity { 
... 

通用实体类只需拥有id和name属性。

这是我如何查询数据。

EntityGraph graph = em.getEntityGraph("graph.author.detail");  
Author author = (Author) em.createQuery("select a from Author a left join a.books b where b.name = 'book 1'") 
          .setHint("javax.persistence.loadgraph", graph).getResultList().get(0); 

这没有用。我期待的作者类返回与书籍属性急于加载,因为它在实体图中指定,但在这种情况下,书籍属性是懒加载和抛出LazyInitialziation异常。 如果我使用where子句的作者属性(例如select a from Author a where a.id = 1),那么它可以正常工作,并且会热切地加载books属性。

任何想法,将不胜感激。

回答

0

我遇到类似的问题JPA 2.1/Hibernate。我相信这可能是因为你已经不得不加入你的查询中的书籍集合,Hibernate忽略了EntityGraph提示。您可以在您的查询中找到最好的'left join fetch'。不只是'left join'.

有一点要注意的是,在我看来,你真正想要的查询是这样的:

"select a from Author a where exists (select 1 from Book b where b.authorId = a.id and b.name = 'book 1')" 

这将返回所有作者的有一个名为'book 1'书。 EntityGraph hint现在可能会正常工作,并且在结果中不会有重复的作者。

而且上面的查询假定您将在AUTHOR_ID柱至少映射到一个字段中作者和图书的实体都,如果不只是做一个双向的关系(在这种情况下,它replace b.authorId = a.authorId with b.author = a.