JPA Criteria API - 如何添加 JOIN 子句(尽可能通用的句子)

发布于 2024-09-12 20:04:52 字数 1378 浏览 5 评论 0原文

我正在尝试动态构建查询,我的下一个目标是添加 JOIN 子句(我不知道如何使用 API)。

例如,到目前为止,这段代码对我有用:(

...
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 实现)

我的愿望是添加 JOIN 子句(尽可能通用)!

我在类 (this.baseClass)

例如:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "assay_id", nullable = false)

那么,在标准 JPA 中是否有类似的方法? (注意:这不能编译)

这里是一个实际的失败方法:

...
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);

对我来说,如果它可以尽可能更通用,那就太好了...:

...
Join joinClause = entity_join(entity_.get("assay_id"), entity2_.get("id"));

当然,我有类(this.baseClass)中的特定注释

感谢您的宝贵时间。我将不胜感激各种评论!

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);

(Note : JpaHandle is from wicket-JPA implementation)

My desire is add JOIN clause (as generical as possible)!

I have the particular annotations in the classes (this.baseClass)

For example :

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "assay_id", nullable = false)

So,Is there a way to something like this in standard JPA ? (Note : this don't compile)

Here a practical fail aproaches :

...
Join<Experiment,Assay> experimentAssays = entity_.join( entity_.get("assay_id") );

Or like that :

...
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"));

Of course, I have the particular annotations in the classes (this.baseClass)

Thank you for your time. I'll appreciate all kind of comments!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

似梦非梦 2024-09-19 20:04:52

也许以下摘录自 第 23 章 - 使用 Criteria API 创建查询< Java EE 6 教程的 /a> 将会提供一些启发(实际上,我建议阅读整个第 23 章):

使用联接查询关系

对于导航到相关的查询
实体类,查询必须定义
通过以下方式加入到相关实体
调用 From.join 方法之一
在查询根对象或其他对象上
加入对象。连接方法有
类似于 JPQL 中的 JOIN 关键字。

连接的目标使用
类型的元模型类
EntityType 指定
的持久字段或属性
加入实体。

join 方法返回一个对象
输入 Join,其中 X
源实体,Y 是目标
加入。

示例 23-10 连接查询

CriteriaQuery; cq = cb.createQuery(Pet.class);
元模型 m = em.getMetamodel();
EntityType<宠物> Pet_ = m.entity(Pet.class);

根<宠物>宠物 = cq.from(Pet.class);
加入<宠物、主人>所有者 = pet.join(Pet_.owners);

连接可以链接在一起
导航至相关实体
无需创建目标实体
每个连接都有一个 Join 实例。

示例 23-11 链接在一起
在查询中

CriteriaQuery; cq = cb.createQuery(Pet.class);
元模型 m = em.getMetamodel();
EntityType<宠物> Pet_ = m.entity(Pet.class);
EntityType<所有者> Owner_ = m.entity(Owner.class);

根<宠物>宠物 = cq.from(Pet.class);
加入<所有者,地址>地址 = cq.join(Pet_.owners).join(Owner_.addresses);

虽如此,我还有一些补充说明:

首先,代码中的以下行:

Root entity_ = cq.from(this.baseClass);

让我认为您以某种方式错过了静态元模型类部分。元模型类(例如引用示例中的Pet_)用于描述持久类的元信息。它们通常是使用注释处理器(规范元模型类生成的,或者可以由开发人员编写(非规范元模型)。但你的语法看起来很奇怪,我认为你正在尝试模仿你错过的东西。

其次,我真的认为你应该忘记这个 assay_id 外键,你在这里走错了路。您确实需要开始考虑对象和关联,而不是表和列。

第三,我不太确定通过添加尽可能通用的 JOIN 子句来准确理解您的意思以及您的对象模型是什么样子,因为您没有提供它(请参阅上一点) 。因此不可能更准确地回答你的问题。

总而言之,我认为您需要阅读更多有关 JPA 2.0 Criteria 和 Metamodel API 的内容,我强烈推荐以下资源作为起点。

另请参阅

相关问题

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):

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 another
join object. The join methods are
similar to the JOIN keyword in JPQL.

The target of the join uses the
Metamodel class of type
EntityType<T> to specify the
persistent field or property of the
joined entity.

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.

Example 23-10 Joining a Query

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);

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.

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);

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.

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.

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.

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.

See also

Related question

眼眸里的那抹悲凉 2024-09-19 20:04:52

实际上,如果您的注释正确,您不必处理静态元模型。

对于以下实体:

@Entity
public class Pet {
  @Id
  protected Long id;
  protected String name;
  protected String color;
  @ManyToOne
  protected Set<Owner> owners;
}

@Entity
public class Owner {
  @Id
  protected Long id;
  protected String name;
}

您可以使用它:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Metamodel m = em.getMetamodel();
EntityType<Pet> petMetaModel = m.entity(Pet.class);

Root<Pet> pet = cq.from(Pet.class);
Join<Pet, Owner> owner = pet.join(petMetaModel.getSet("owners", Owner.class));

Actually you don't have to deal with the static metamodel if you had your annotations right.

With the following entities :

@Entity
public class Pet {
  @Id
  protected Long id;
  protected String name;
  protected String color;
  @ManyToOne
  protected Set<Owner> owners;
}

@Entity
public class Owner {
  @Id
  protected Long id;
  protected String name;
}

You can use this :

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Metamodel m = em.getMetamodel();
EntityType<Pet> petMetaModel = m.entity(Pet.class);

Root<Pet> pet = cq.from(Pet.class);
Join<Pet, Owner> owner = pet.join(petMetaModel.getSet("owners", Owner.class));
不…忘初心 2024-09-19 20:04:52

警告! Sun JPA 2 示例以及 Pascal 答案中粘贴的内容存在许多错误。请参阅这篇文章

这篇文章和 Sun Java EE 6 JPA 2 示例确实阻碍了我对 JPA 2 的理解。在仔细研究了 Hibernate 和 OpenJPA 手册并认为我对 JPA 2 有了很好的理解之后,当我回到这篇文章时仍然感到困惑。

Warning! There's a numbers of errors on the Sun JPA 2 example and the resulting pasted content in Pascal's answer. Please consult this post.

This post and the Sun Java EE 6 JPA 2 example really held back my comprehension of JPA 2. After plowing through the Hibernate and OpenJPA manuals and thinking that I had a good understanding of JPA 2, I still got confused afterwards when returning to this post.

不及他 2024-09-19 20:04:52

你不需要学习JPA。您可以使用我的 JPA2 简易标准 (https://sourceforge.net/projects/easy-标准/文件/)。这是示例

CriteriaComposer<Pet> petCriteria CriteriaComposer.from(Pet.class).
where(Pet_.type, EQUAL, "Cat").join(Pet_.owner).where(Ower_.name,EQUAL, "foo");

List<Pet> result = CriteriaProcessor.findAllEntiry(petCriteria);

List<Tuple> result =  CriteriaProcessor.findAllTuple(petCriteria);

You don't need to learn JPA. You can use my easy-criteria for JPA2 (https://sourceforge.net/projects/easy-criteria/files/). Here is the example

CriteriaComposer<Pet> petCriteria CriteriaComposer.from(Pet.class).
where(Pet_.type, EQUAL, "Cat").join(Pet_.owner).where(Ower_.name,EQUAL, "foo");

List<Pet> result = CriteriaProcessor.findAllEntiry(petCriteria);

OR

List<Tuple> result =  CriteriaProcessor.findAllTuple(petCriteria);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文