JPA Criteria API - 如何添加 JOIN 子句(尽可能通用的句子) [英] JPA Criteria API - How to add JOIN clause (as general sentence as possible)
问题描述
我正在尝试动态构造查询,我的下一个目标是添加 JOIN 子句(我不知道如何使用 API).
I am trying to construct queries dynamically, and my next target is add JOIN clauses (I don't know how can I use the API).
现在,例如,这段代码对我有用:
By now, for example, this code work for me :
...
Class baseClass;
...
CriteriaBuilder cb = JpaHandle.get().getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery(this.baseClass);
Root entity_ = cq.from(this.baseClass);
Predicate restrictions = null;
...
restrictions = cb.conjunction();
restrictions = cb.and(restrictions, entity_.get("id").in(this.listId));
...
cq.where(restrictions);
...
Query qry = JpaHandle.get().createQuery(cq);
(注意:JpaHandle 来自 wicket-JPA 实现)
(Note : JpaHandle is from wicket-JPA implementation)
我的愿望是添加 JOIN 子句(尽可能通用)!
我在类(this.baseClass)中有特定的注释
I have the particular annotations in the classes (this.baseClass)
例如:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "assay_id", nullable = false)
那么,有没有办法在标准 JPA 中做到这一点?(注意:这不会编译)
So,Is there a way to something like this in standard JPA ? (Note : this don't compile)
这里有一个实际的失败方法:
...
Join<Experiment,Assay> experimentAssays = entity_.join( entity_.get("assay_id") );
或者像这样:
...
CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
Root<Customer> c = q.from(Customer.class);
SetJoin<Customer, PurchaseOrder> o = c.join(Customer_.orders);
对我来说,如果它可以更通用,那就太好了......:
For me, if it could be more generical as possible it will be great... :
...
Join joinClause = entity_join(entity_.get("assay_id"), entity2_.get("id"));
当然,我在类(this.baseClass)中有特定的注释
Of course, I have the particular annotations in the classes (this.baseClass)
感谢您的时间.我会感谢所有类型的评论!
Thank you for your time. I'll appreciate all kind of comments!
推荐答案
也许以下摘自 第 23 章 - Java EE 6 教程的第 23 章 - 使用 Criteria API 创建查询 将提供一些启发(实际上,我建议阅读整个第 23 章):
Maybe the following extract from the Chapter 23 - Using the Criteria API to Create Queries of the Java EE 6 tutorial will throw some light (actually, I suggest reading the whole Chapter 23):
对于导航到相关的查询实体类,查询必须定义加入相关实体调用 From.join
方法之一在查询根对象或其他join
对象.加入方法是类似于 JPQL 中的 JOIN
关键字.
Querying Relationships Using Joins
For queries that navigate to related entity classes, the query must define a join to the related entity by calling one of the
From.join
methods on the query root object, or anotherjoin
object. The join methods are similar to theJOIN
keyword in JPQL.
连接的目标使用元模型类类型EntityType
指定的持久字段或属性加入的实体.
The target of the join uses the
Metamodel class of type
EntityType<T>
to specify the
persistent field or property of the
joined entity.
join 方法返回一个对象输入 Join
,其中 X
是源实体和 Y
是目标加入.
The join methods return an object of
type Join<X, Y>
, where X
is the
source entity and Y
is the target of
the join.
示例 23-10 加入查询
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Metamodel m = em.getMetamodel();
EntityType<Pet> Pet_ = m.entity(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
Join<Pet, Owner> owner = pet.join(Pet_.owners);
Join 可以链接在一起导航到相关实体目标实体而无需创建每个连接的 Join
实例.
Joins can be chained together to
navigate to related entities of the
target entity without having to create
a Join<X, Y>
instance for each join.
示例 23-11 链接连接在一起在查询中
Example 23-11 Chaining Joins Together in a Query
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Metamodel m = em.getMetamodel();
EntityType<Pet> Pet_ = m.entity(Pet.class);
EntityType<Owner> Owner_ = m.entity(Owner.class);
Root<Pet> pet = cq.from(Pet.class);
Join<Owner, Address> address = cq.join(Pet_.owners).join(Owner_.addresses);
话虽如此,我还有一些补充说明:
That being said, I have some additional remarks:
首先,代码中的以下行:
First, the following line in your code:
Root entity_ = cq.from(this.baseClass);
让我觉得你不知何故错过了静态元模型类部分.引用示例中的Pet_
等元模型类用于描述持久化类的元信息.它们通常使用注释处理器生成(规范元模型类),或者可以由开发人员编写(非规范元模型).但是你的语法看起来很奇怪,我想你是在模仿你错过的东西.
Makes me think that you somehow missed the Static Metamodel Classes part. Metamodel classes such as Pet_
in the quoted example are used to describe the meta information of a persistent class. They are typically generated using an annotation processor (canonical metamodel classes) or can be written by the developer (non-canonical metamodel). But your syntax looks weird, I think you are trying to mimic something that you missed.
第二,我真的认为你应该忘记这个 assay_id
外键,你在这里走错了路.您确实需要开始考虑对象和关联,而不是表和列.
Second, I really think you should forget this assay_id
foreign key, you're on the wrong path here. You really need to start to think object and association, not tables and columns.
第三,我不太确定通过添加尽可能通用的 JOIN 子句 以及您的对象模型是什么样子,因为您没有提供它(请参阅前一点).因此,无法更准确地回答您的问题.
Third, I'm not really sure to understand what you mean exactly by adding a JOIN clause as generical as possible and what your object model looks like, since you didn't provide it (see previous point). It's thus just impossible to answer your question more precisely.
总而言之,我认为您需要阅读更多有关 JPA 2.0 Criteria 和 Metamodel API 的内容,我热烈推荐以下资源作为起点.
To sum up, I think you need to read a bit more about JPA 2.0 Criteria and Metamodel API and I warmly recommend the resources below as a starting point.
- JPA 2.0 规范中的 6.2.1 静态元模型类部分
- JPA 2.0 中的动态类型安全查询
- 使用 Criteria API 和 Metamodel API 创建基本类型安全查询
这篇关于JPA Criteria API - 如何添加 JOIN 子句(尽可能通用的句子)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!