【问题标题】:JPA Criteria API NOT IN Code Simplification and OptimizationJPA Criteria API 不在代码简化和优化中
【发布时间】:2016-05-21 06:32:51
【问题描述】:

我是 JPA 标准 API 的新手。

2 个问题:

  1. 如何进一步简化此方法,第 3 条和第 4 条语句都需要类参数?
  2. 如何将NOT IN 操作转换为NOT EXISTS 以提高性能?

    public List<Pilot> getPilotsExcept(final Integer... entityIds) {
    
      final CriteriaBuilder critBuilder = em.getCriteriaBuilder();
    
      final CriteriaQuery<Pilot> critQuery =
            critBuilder.createQuery(getEntityClass());
    
      final Root<Pilot> root = critQuery.from(getEntityClass());  // Why pass the class again?
    critQuery.select(root).where(
        critBuilder.not(root.get("id").in(Arrays.asList(entityIds))));
    
      final TypedQuery<Pilot> typedQuery = em.createQuery(critQuery);
      return typedQuery.getResultList();
    }
    

【问题讨论】:

标签: java jpa criteria-api


【解决方案1】:

为什么又考过了?

在 Criteria API 中,查询组件由对象表示。所以select子句和from子句用对象来表示:

  • select 子句表示如下:

    CriteriaQuery<Pilot> critQuery = critBuilder.createQuery(getEntityClass());
    

    上一行中的Pilot类代表查询结果的返回类型。

  • 另一方面,查询的from 子句定义如下:

    final Root<Pilot> root = critQuery.from(getEntityClass());
    

在此示例中,RootCriteriaQuery 恰好具有相同的类型。但并非所有查询都如此。在某些查询中,您可能希望从查询中返回一个或多个属性(但不是查询中涉及的实体的所有属性)。在这些情况下,您在CriteriaQuery 中指定的类型将不同于您在Root 中使用的类型。例如,假设您的Pilot 实体中有一个name 属性,并且您只对Pilot 实体的名称列表感兴趣。在这种情况下,您的CriteriaQuery 将定义如下:

    CrtieriaQuery<String> cq = cb.createQuery(String.class);

但在您的示例中,Root 的定义没有改变。

不存在表达式

为了能够将您的 not in 表达式转换为 not exists 表单,您必须使用 id 制定子查询。以下是 JPA 规范的摘录:

EXISTS 表达式是一个谓词,仅当子查询的结果包含一个或多个值时为真,否则为假。 存在表达式的语法是

exists_expression::= [NOT] EXISTS(子查询) 当然,这必须翻译成 Criteria API,在这种情况下,语法将是

不(存在(子查询))。

下面是一个创建子查询的例子(伪代码):

Subquery<Integer> sq = critQuery.subquery(Integer.class);
Root<Pilot> pilot = sq.from(Pilot.class);
sq.select(pilot.<Integer>get("id"));
sq.where(<some_condition>);

【讨论】:

  • 你很好地解释了这两点。我确实注意到代码在测试期间删除了所有内容并且我能够更正它,我现在有信心根据您的解释将代码翻译为not exists。感谢您的全面回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-25
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-04
相关资源
最近更新 更多