【问题标题】:JPA Criteria API - How to add JOIN clause (as general sentence as possible)JPA Criteria API - 如何添加 JOIN 子句(尽可能一般的句子)
【发布时间】:2011-03-26 09:05:57
【问题描述】:

我正在尝试动态构造查询,我的下一个目标是添加 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)中有特定的注解

感谢您的宝贵时间。我会感谢所有类型的 cmets!

【问题讨论】:

  • 您能提供带注释的域类或其他示例类吗?

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


【解决方案1】:

也许 Java EE 6 教程的Chapter 23 - Using the Criteria API to Create Queries 的以下摘录会有所启发(实际上,我建议阅读整个第 23 章):

Querying Relationships Using Joins

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

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

连接方法返回一个对象 键入Join&lt;X, Y&gt;,其中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);

连接可以链接在一起 导航到相关实体 无需创建目标实体 每个连接都有一个 Join&lt;X, Y&gt; 实例。

示例 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 的内容,我强烈推荐以下资源作为起点。

另见

相关问题

【讨论】:

  • "加入地址 = cq.join(Pet_.owners).join(Owner_.addresses);"哇,这真的应该工作吗?或者它曾经做过一次? CriteriaQuery 甚至没有“加入”方法。哎呀!
  • 您好,是否可以加入条件例如:address.on(cb.greatest(addresses.get("id")));
【解决方案2】:

您不需要学习 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);

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

【讨论】:

    【解决方案3】:

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

    具有以下实体:

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

    【讨论】:

    • 你能举一个“正确”注释的例子吗?
    【解决方案4】:

    警告! Sun JPA 2 示例和 Pascal 答案中的粘贴内容存在许多错误。请咨询this post

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

    【讨论】:

    • 一旦你掌握了基础知识,是否有好的教程或文档? Pro JPA 2 Mastering the Java Persistence API 比 sun 教程要好得多,但没有详细说明。我很难使用 Criteria API 创建复杂的联接,也找不到大量的文档和示例。
    • @april26 - 我通过反复试验了解到在我的 WAS 8 输出控制台中启用 OpenJPA 的日志记录。我能够看到 Criteria API 正在生成的 SQL 并对其进行修改,直到它吐出我期望看到的查询。在此之前,我浏览了 Hibernate 和 OpenJPA 的手册(两者都很庞大,但在 Criteria API 上的部分相对较小)。我记得一篇 IBM 文章也谈到了它。
    猜你喜欢
    • 1970-01-01
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 2017-07-20
    • 1970-01-01
    • 2012-07-19
    • 1970-01-01
    相关资源
    最近更新 更多