我使用jpa 2.1 EntityGraphs来修改不同的jpa查询,在某些情况下,EntityGraphs没有按预期工作。我正在努力的简单用例是
作为父类,具有与Book子类的单向一对多关系的父类,我想检索给定书名的作者结果,如findAllAuthorsByBookName。
我的作者类看起来像这样
@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>();
....
Book没有对作者的引用,所以它看起来像这样
@Entity
public class Book extends GenericEntity {
...
Generic Entity类只具有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);
这不起作用。我希望返回Author类,并且热切地加载books属性,因为它在实体图中指定但在这种情况下books属性是延迟加载并抛出LazyInitialziation异常。
相反,如果我在作者的where子句(例如select a from Author a where a.id = 1
)上使用了一个属性,那么它可以正常工作并急切地加载books属性。
任何想法都会受到赞赏。
答案 0 :(得分: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列映射到Author和Book实体中的字段,如果不是仅仅建立双向关系(在这种情况下它是replace b.authorId = a.authorId with b.author = a.
)