当我在实体下面时。
@Entity
class Article {
@OneToMany
Set<Comment> comments;
}
@Entity
class Comment {
@ManyToOne
User author;
}
使用EntityGraph和静态元模型创建一些视图规范类,如下所示。
class ArticleViewSpec {
/**
* fetch comments and each of comment's author.
*/
public static final Function<EntityManager, EntityGraph<Article>> DETAIL = em -> {
EntityGraph<Article> graph = em.createEntityGraph(Article.class);
Subgraph<Comment> sgComment = graph.addSubgraph(Article_.comments);
sgComment.addAttributeNodes(Comment_.author);
return graph;
};
}
但是上面的课程无法编译,因为期望的类型不是
Subgraph<Comment> sgComment = graph.addSubgraph(Article_.comments);
但
Subgraph<Set<Comment>> sgComment = graph.addSubgraph(Article_.comments);
当我们拥有扩展javax.persistence.metamodel.PluralAttribute
的属性时会发生此问题。
(例如SetAttribute,ListAttribute)
这种行为显然来自API规范。
javax.persistence.EntityGraph#addSubgraph(javax.persistence.metamodel.Attribute<T,X>)
但是如何在这些情况下使用JPA静态MetaModel以可编程方式和类型安全地创建EntityGraph?
/**
* fetch comments and each of comment's author.
*/
public static final Function<EntityManager, EntityGraph<Article>> DETAIL = em -> {
EntityGraph<Article> graph = em.createEntityGraph(Article.class);
Subgraph<Comment> sgComment =
graph.addSubgraph(Article_.comments.getName(), Comment.class);
sgComment.addAttributeNodes(Comment_.author);
return graph;
};
答案 0 :(得分:1)
我遇到了同样的问题,经过一些研究后我很确定这是JPA API 中的一个缺陷。
EclipseLink中的实现似乎做了正确的事情:
public <T> Subgraph<T> addSubgraph(Attribute<X, T> attribute) {
Class type = attribute.getJavaType();
if (attribute.isCollection()) {
type = ((PluralAttribute) attribute).getBindableJavaType();
}
return addSubgraph(attribute.getName(), type);
}
注意当给出PluralAttribute
时,实现如何违反界面中的声明:T
的{{1}}为Attribute
,该方法执行不实际返回Collection<something>
声明,而是Subgraph<Collection<something>>
的实例。
对我而言,看起来API在这方面实际上已被打破,似乎没有人关心,因为可能没有多少人使用Subgraph<something>
s 和静态元模型,尽管这将是一件好事。
有人应该在某处创建一个问题,以便修复API的这一部分。
我对此问题的当前“修复”是一种自定义EntityGraph
,它接受EntityGraphBuilder
和SingularAttribute<E,X>
以允许PluralAttribute<E,?,X>
的类型安全创建。基本上,我只是让我的EntityGraph
表示树中的属性或节点,并通过类型安全的泛型方法将它们连接在一起。这样做的好处是可以在公共API下合并不同的for-cause-whatever EntityGraphElement
和EntityGraph
接口,以便可以创建和使用SubGraph
表示并将其重新用作子图在其他实体图中。
我的解决方案也可能应用于JPA API,它基本上只是拆分
EntityGraph
分为两种方法:
<T> Subgraph<T> addSubgraph(Attribute<X, T> attribute)
和
<F> EntityGraphElement<F> fetch(SingularAttribute<? super T, F> attr);
更新
使用一些泛型Voodoo,一个方法就足够了:
<F> EntityGraphElement<F> fetch(PluralAttribute<? super T, ?, F> attr);