JPA2 Criteria API 更可取的真实示例都有哪些?

Posted

技术标签:

【中文标题】JPA2 Criteria API 更可取的真实示例都有哪些?【英文标题】:What are some of the real world example where JPA2 Criteria API is more preferable?JPA2 Criteria API 更可取的真实示例有哪些? 【发布时间】:2011-03-26 03:30:43 【问题描述】:

我查看了 JPA 2.0 Criteria API,但我发现它不像 Hibernate Criteria 那样繁琐。是否有充分的理由使用 JPA 2.0 Criteria API 而不是使用 JPA-QL?感谢您的建议。

【问题讨论】:

这个问题本质上是hibernate query language or using criteria或Hibernate: Criteria vs. HQL的复制品,因为利弊是一样的。 并非如此。 JPA 2.0 标准 API 并不像 Hibernate 标准那么简单。之前用过Hibernate条件,感觉JPA 2.0条件API感觉有点麻烦。 实际上,我省略了一个非常重要的区别,我将在答案中介绍。 【参考方案1】:

与 Hibernate Criteria API 一样,JPA 2.0 Criteria API 特别适合动态构建查询,以处理查询结构因运行时条件而异的情况。

但还有更多。虽然比 Hibernate 的 Criteria API 更冗长,但 JPA Criteria API 允许构建 typesafe 查询(如果您使用 Metamodel API)。下面是一个例子:

EntityManager em = ...
QueryBuilder qb = em.getQueryBuilder();
CriteriaQuery<Person> c = qb.createQuery(Person.class);
Root<Person> p = c.from(Person.class);
Predicate condition = qb.gt(p.get(Person_.age), 20);
c.where(condition);
TypedQuery<Person> q = em.createQuery(c); 
List<Person> result = q.getResultList();

在上面的sn-p中,下面的例子会引发编译错误:

Predicate condition = qb.gt(p.get(Person_.age, "xyz"));

如果您想知道,Person_静态的、实例化的、规范的元模型类,对应于原始的 Person 实体类(由注释处理器生成)。它为基于运行时反射的方法提供了一种强类型替代方案:

Field field = Person.class.getField("age");

优点:

类型安全,编译时验证! 禁止构造语法错误的查询。 重构后可能会引发编译错误。 为自动完成提供开箱即用的支持 更适合动态查询。

缺点:

更详细。 可读性较差。

总的来说,我觉得 JPQL 更舒服,但 Criteria API 的类型安全性是与 JPQL(以及 Hibernate Criteria API)的主要区别。

另见

Using the Criteria API and Metamodel API to Create Basic Type-Safe Queries Dynamic, typesafe queries in JPA 2.0 Comparing JPQL, Criteria string-based and typesafe queries A typesafe criteria query API for JPA

相关答案

Dynamic JPA 2.0 query using Criteria API hibernate query language or using criteria Hibernate: Criteria vs. HQL

【讨论】:

感谢帕斯卡的解释。我不会想到的。 我有一个问题,为什么在代码中你没有使用我在其他示例中找到的核心:Metamodel m = em.getMetamodel(); EntityType Pet_ = m.entity(Pet.class);【参考方案2】:

JPA 2.0 Criteria API 是用于构建查询的基于对象的 API。我认为当你有一个动态查询它可以发挥很好的作用,它可以变得更具可读性如下

cq.select(...)
  .where(...)
  .orderBy(...)
  .groupBy(...);

但在使用静态查询时更喜欢使用外部化、可维护和可读的文件

<entity-mappings>
    ...
    <named-query name="ORDER">
       <query>
           <![CDATA[
               from
                   Order
           ]]>
       </query>
    </named-query>
    <named-query name="ORDER_WITH_LINE_ITEM">
       <query>
           <![CDATA[
               from
                   Order o
               inner join fetch 
                   o.lineItemList
           ]]>
       </query>
    </named-query>
    ...
</entity-mappings>

如果您有一个模块化应用程序,请为每个模块使用一个 xml 文件,如下所示

br
   com
       ar
           moduleA
               model
                   repository
                       moduleA.xml
           moduleB
               model
                   repository
                       moduleB.xml               
           moduleC
               model
                   repository
                       moduleC.xml

然后你定义你的 mappinf-file 元素

<mapping-file>br/com/ar/moduleA/model/repository/moduleA.xml</mapping-file>
<mapping-file>br/com/ar/moduleB/model/repository/moduleB.xml</mapping-file>
<mapping-file>br/com/ar/moduleC/model/repository/moduleC.xml</mapping-file>

【讨论】:

不错。我认为这更像是 Rails3.0 中的 Arel。感谢分享。【参考方案3】:

如果您生成实体元模型,则可以以静态类型的形式使用 JPA 2 标准。它比 JPQL 更冗长,但是是静态类型的,并且直接支持动态查询构造。

静态类型查询语言的好处是您可以在编译时捕获更多错误,并且还可以使用自动完成等 IDE 功能。

【讨论】:

【参考方案4】:

对我来说,JPA2 大放异彩的真实示例是当您需要根据用户的输入创建查询时。我不是在谈论一个非常简单的地方,只有一个参数。我的意思是当您在应用程序中设置了高级搜索选项时。填充某个参数时需要连接的一种。您不需要连接您的 HQL 或 SQL 以包含大量参数、额外的连接和函数。自定义 SQL 需要大量测试来证明它有效。向 HQL 和 SQL 添加额外的搜索选项需要大量返工,而在 JPA 中这可能更简单。

【讨论】:

以上是关于JPA2 Criteria API 更可取的真实示例都有哪些?的主要内容,如果未能解决你的问题,请参考以下文章

比较 JPA Criteria API 中的日期实体

通过 Criteria api 在 LIKE 中转义字符

使用 JPA Criteria API,你能做一个只导致一个连接的 fetch join 吗?

JPA Criteria builder IN 子句查询

Specifications查询

jpa多条件查询重写Specification的toPredicate方法(转)