【发布时间】:2019-02-14 19:25:14
【问题描述】:
我正在尝试使用 CriteriaQuery 编写 SQL 查询,但我很难做到。这个查询基本上是获取一个发货清单并按授权日期对它们进行排序。此授权日期表示为状态转换消息表中第一条记录的日期属性,初始状态为 3,最终状态为 4。这是我的查询:
SELECT s.id
FROM shipment s
ORDER BY (SELECT min(stm.date)
FROM status_transition_message stm
WHERE stm.initial_status = 1 AND stm.final_status = 3 AND stm.shipment_id = s.id) desc;
我尝试了多种不同的解决方案,但到目前为止都没有奏效。
我当前的迭代如下:
private void sortByAuthDate(Root<ShipmentTbl> root, CriteriaQuery<?> query, CriteriaBuilder builder, ListSort sort) {
Subquery<Timestamp> authDateQuery = query.subquery(Timestamp.class);
Root<StatusTransitionMessageTbl> stmRoot = authDateQuery.from(StatusTransitionMessageTbl.class);
Predicate shipmentId = builder.equal(stmRoot.<ShipmentTbl>get("shipment").<String>get("id"), root.<String>get("id"));
Predicate initialStatus = builder.equal(stmRoot.<Integer>get("initialStatus"), 3);
Predicate finalStatus = builder.equal(stmRoot.<Integer>get("finalStatus"), 4);
// returns the authorization date for each queried shipment
authDateQuery.select(builder.least(stmRoot.<Timestamp>get("date")))
.where(builder.and(shipmentId, initialStatus, finalStatus));
Expression<Timestamp> authDate = authDateQuery.getSelection();
Order o = sort.getSortDirection() == ListSort.SortDirection.ASC ? builder.asc(authDate) : builder.desc(authDate);
query.multiselect(authDate).orderBy(o);
}
这个方案的问题是CriteriaQuery生成的SQL查询不支持ORDER BY子句中的子查询,导致解析异常。
【问题讨论】:
-
为什么要将此 SQL 查询重写为 JPQL / Criteria Query?你不能继续使用 SQL,因为它更容易工作吗?
-
因为我们当前的平台已经在使用 CriteriaQuery 来设置数据库查询的过滤器,以及对数据库进行实际的查询,所以还必须使用 CriteriaQuery 实现排序
-
如果您绝对必须这样做,您仍然可以在数据库中使用视图。标准查询不会注意到。但我会真诚地重新考虑将相对有限的 API 用于everything。有一些选项,你知道 :) 想象一下用这个 API 计算一个运行总数......
标签: java jpa criteria-api