JPA 标准 API - 如何添加 JOIN 子句(尽可能一般句子)

2022-08-31 20:13:33

我正在尝试动态构造查询,我的下一个目标是添加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来自检票口-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)

感谢您抽出宝贵时间接受采访。我将不胜感激各种评论!


答案 1

也许下面的摘录来自Java EE 6教程的第23章 - 使用标准API创建查询会带来一些启发(实际上,我建议阅读整个第23章):

使用联接查询关系

对于导航到相关实体类的查询,查询必须通过调用查询根对象上的一个方法或另一个对象来定义与相关实体的联接。连接方法类似于 JPQL 中的关键字。From.joinjoinJOIN

联接的目标使用 Metamodel 类型的类来指定联接实体的持久性字段或属性。EntityType<T>

连接方法返回一个对象类型为 ,其中 是源实体,并且是连接的目标。Join<X, Y>XY

示例 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<X, Y>

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

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

话虽如此,我还有一些补充意见:

首先,代码中的以下行:

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

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

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

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

总而言之,我认为您需要阅读更多有关JPA 2.0标准和元模型API的信息,我强烈建议以下资源作为起点。

另请参见

相关问题


答案 2

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

具有以下实体:

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

推荐