【问题标题】:JPA CriteriaQuery with LEAST and GREATEST functions具有 LEAST 和 GREATEST 函数的 JPA CriteriaQuery
【发布时间】:2018-12-14 06:06:40
【问题描述】:

我有一个问题,我需要使用 LEAST 和 GREATEST 函数连接两个表,但使用 JPA CriteriaQuery。这是我要复制的 SQL...

select * from TABLE_A a
inner join TABLE_X x on
(
  a.COL_1 = least(x.COL_Y, x.COL_Z)
  and
  a.COL_2 = greatest(x.COL_Y, x.COL_Z)
);

我查看了 CriteriaBuilder.least(..)greatest(..),但很难理解如何创建 Expression<T> 以传递给任一函数。

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    比较两列并获得最小/最大值的最简单方法是使用 CASE 语句。

    在 JPQL 中,查询看起来像

    select a from EntityA a join a.entityXList x
      where a.numValueA=CASE WHEN x.numValueY <= x.numValueZ THEN x.numValueY ELSE x.numValueZ END
      and   a.numValueB=CASE WHEN x.numValueY >= x.numValueZ THEN x.numValueY ELSE x.numValueZ END 
    

    您可以使用CriteriaBuilder.selectCase() 编写等效代码,但我从来都不是 CriteriaBuilder 的忠实粉丝。如果需求迫使您使用 CriteriaBuilder,请告诉我,我可以尝试编写等效代码。

    CriteriaBuilder 最小/最大旨在获取一列中所有条目的最小/最大值。假设您想要获取具有按字母顺序排列的最大字符串名称的实体。代码看起来像

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery query = cb.createQuery(EntityX.class);
    Root<EntityX> root = query.from(EntityX.class);
    
    Subquery<String> maxSubQuery = query.subquery(String.class);
    Root<EntityX> fromEntityX = maxSubQuery.from(EntityX.class);
    maxSubQuery.select(cb.greatest(fromEntityX.get(EntityX_.nameX)));
    query.where(cb.equal(root.get(EntityX_.nameX), maxSubQuery));
    

    我创建了一个示例 Spring Data JPA 应用程序,用于演示这些 JPA 示例

    https://github.com/juttayaya/stackoverflow/tree/master/JpaQueryTest

    【讨论】:

    • 不幸的是,在我的情况下,通过 CriteriaBuilder 定义最小/最大谓词是一项要求。因为,正如您所指出的,最大和最小都是对单个表达式(例如列)进行操作的聚合函数,我们需要将两列转换为一列,可能通过您上面建议的枢轴或子选择操作.幸运的是,还有另一种方法可以调用我希望实现的函数...
    【解决方案2】:

    事实证明,CriteriaBuilder 确实支持将 LEAST 和 GREATEST 作为非聚合函数调用,并且可以通过使用 CriteriaBuilder.function(..) 来访问,如下所示:

    Predicate greatestPred = cb.equal(pathA.get(TableA_.col2),
                        cb.function("greatest", String.class,
                                pathX.get(TableX_.colY), pathX.get(TableX_.colZ)));
    

    【讨论】:

      猜你喜欢
      • 2011-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 2012-08-11
      相关资源
      最近更新 更多