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

时间:2010-08-06 14:24:03

标签: java api join jpa-2.0 criteria-api

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

中有特定的注释

感谢您的时间。我会感谢所有的评论!

4 个答案:

答案 0 :(得分:40)

也许来自Java EE 6教程的Chapter 23 - Using the Criteria API to Create Queries的以下摘录会引起一些启示(实际上,我建议阅读整篇第23章):

  

Querying Relationships Using Joins

     

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

     

联接的目标使用   元模型类型   EntityType<T>指定   持久的领域或财产   加入实体。

     

join方法返回一个对象   键入Join<X, Y>,其中X为。{1}}   源实体和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);
     

联接可以链接在一起   导航到相关的实体   目标实体无需创建   每个联接的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 Criteria和Metamodel API的内容,我热烈推荐以下资源作为起点。

另见

相关问题

答案 1 :(得分:13)

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

您可以使用:

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

答案 2 :(得分: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);

OR

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

答案 3 :(得分:5)

警告! Sun JPA 2示例中存在大量错误,并且Pascal的答案中出现了粘贴的内容。请咨询this post

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