在现实世界中,JPA2 标准 API 更可取的一些示例是什么?

2022-09-01 20:36:35

我已经看了一下JPA 2.0 Criteria API,但我发现它与Hibernate Criteria不同太麻烦了。有没有充分的理由使用 JPA 2.0 Criteria API 而不是使用 JPA-QL?感谢您的建议。


答案 1

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

但还有更多。虽然比Hibernate的Criteria API更详细,但JPA Criteria API允许构建类型安全查询(如果您使用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();

例如,在上面的代码段中,以下内容会引发编译错误:

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

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

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

优点:

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

缺点:

  • 更详细。
  • 可读性较差。

总的来说,我觉得JPQL更舒服,但标准API的类型安全性与JPQL(以及Hibernate Criteria API)有很大的不同。

另请参见

相关解答


答案 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 文件元素

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

推荐