具有LEAST和GREATEST功能的JPA CriteriaQuery

spa*_*iff 4 java hibernate jpa

我有一个问题,我需要使用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)
);
Run Code Online (Sandbox Code Playgroud)

我看过CriteriaBuilder.least(..)最大的(..),但我很难理解如何创建Expression<T>传递给任一函数.

Jir*_*aya 9

比较两列并获得最小/最大值的最简单方法是使用 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 
Run Code Online (Sandbox Code Playgroud)

您可以使用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));
Run Code Online (Sandbox Code Playgroud)

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

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


spa*_*iff 7

事实证明,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)));
Run Code Online (Sandbox Code Playgroud)