JPA Criteria API - 如何添加JOIN子句(作为一般句子)

Man*_*dor 31 java api join criteria-api jpa-2.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);
Run Code Online (Sandbox Code Playgroud)

(注意:JpaHandle来自wicket-JPA实现)

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

我在类中有特定的注释(this.baseClass)

例如 :

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "assay_id", nullable = false)
Run Code Online (Sandbox Code Playgroud)

那么,在标准JPA中有没有这样的方法呢?(注意:这不编译)

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

...
Join<Experiment,Assay> experimentAssays = entity_.join( entity_.get("assay_id") );
Run Code Online (Sandbox Code Playgroud)

或者像那样:

...
CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
Root<Customer> c = q.from(Customer.class);
SetJoin<Customer, PurchaseOrder> o = c.join(Customer_.orders);
Run Code Online (Sandbox Code Playgroud)

对我来说,如果它可能更加通用,它会很棒......:

...
Join joinClause = entity_join(entity_.get("assay_id"), entity2_.get("id"));
Run Code Online (Sandbox Code Playgroud)

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

感谢您的时间.我会感谢各种评论!

Pas*_*ent 41

也许第23章 - 使用Criteria API创建 Java EE 6教程查询的以下摘录将会有所启发(实际上,我建议阅读整个第23章):

使用连接查询关系

对于导航到相关实体类的查询,查询必须通过调用From.join查询根对象或其他join对象上的方法 之一来定义与相关实体的连接.连接方法类似于JOINJPQL中的关键字.

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

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

示例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);
Run Code Online (Sandbox Code Playgroud)

可以将联接链接在一起以导航到目标实体的相关实体,而无需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);
Run Code Online (Sandbox Code Playgroud)

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

首先,代码中的以下行:

Root entity_ = cq.from(this.baseClass);
Run Code Online (Sandbox Code Playgroud)

让我觉得你错过了静态元模型类部分.诸如Pet_引用示例中的元模型类用于描述持久类的元信息.它们通常产生使用注释处理器(规范元模型类),或者可以由开发者(被写入非规范元模型).但是你的语法看起来很奇怪,我想你正试图模仿你错过的东西.

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

第三,我不太确定通过添加JOIN子句尽可能通用以及你的对象模型看起来完全理解你的意思,因为你没有提供它(见前一点).因此,更准确地回答你的问题是不可能的.

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

也可以看看

相关问题

  • “加入&lt;所有者,地址&gt;地址 = cq.join(Pet_.owners).join(Owner_.addresses);” 哇哦,这真的应该有效吗?或者也许它曾经做过?CriteriaQuery 甚至没有“join”方法。哎呀! (2认同)
  • 嗨,是否有可能加入条件,例如:`address.on(cb.greatest(addresses.get("id")));`? (2认同)

Chr*_*oix 15

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

你可以用这个:

@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;
}
Run Code Online (Sandbox Code Playgroud)

  • 你能举一个“正确”注释的例子吗? (3认同)

小智 5

您不需要学习JPA.您可以使用我的简单标准JPA2(https://sourceforge.net/projects/easy-criteria/files/).这是一个例子

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);
Run Code Online (Sandbox Code Playgroud)

要么

List<Tuple> result =  CriteriaProcessor.findAllTuple(petCriteria);
Run Code Online (Sandbox Code Playgroud)


Chr*_*ris 5

警告!Sun JPA 2示例中存在大量错误,并且Pascal的答案中出现了粘贴的内容.请查阅这篇文章.

这篇文章和Sun Java EE 6 JPA 2示例真正阻碍了我对JPA 2的理解.在浏览了Hibernate和OpenJPA手册并认为我对JPA 2有了很好的理解之后,我在回到这篇文章后仍然感到困惑. .