使用 JPA CriteriaBuilder API 实现 NULLS LAST

Implementing NULLS LAST with JPA CriteriaBuilder API

Spring/Hibernate/MySQL/JPA 这里。我有以下代码:

public void setOrdering(
    SearchRequest searchRequest,
    CriteriaQuery query,
    CriteriaBuilder builder,
    Root<? extends MyEntity> root) {

  String sortParam = "reportedOn";

  Expression expression = builder.selectCase()
    .when(builder.isNull(root.get(sortParam)), root.get(sortParam))
    .otherwise(root.get(sortParam));

  Order order = (searchRequest.isAscending())
    ? builder.asc(expression)
    : builder.desc(expression);

  query.orderBy(order);

}

基本上,我正在尝试实现 CriteriaBuilder/JPA 等效项:

SELECT
  *
FROM
  mytable
WHERE
  <lots of predicates here>
ORDER BY reported_on IS NULL, reported_on <ASC/DESC>

我已经添加了 WHERE 谓词,我只是在努力处理 query.orderBy(...)

在运行时,当 searchRequest.isAscending() 为 false 时,结果返回时工作正常,包含 null reported_on 值的记录排在结果末尾。

但如果 searchRequest.isAscending() 为真,NULLS LAST 尝试似乎根本不起作用。

您混淆了 Spring 和 JPA API,此处 query 来自 JPA API,因此您需要使用类似以下内容进行排序:

CriteriaBuilder cb = ...
Root root = ...
query.orderBy(cb.asc(root.get("reportedOn")));

看起来 JPA 的 CriteriaBuilder 不支持 NULLS LAST。我实际上是使用 SQL “hack”:

String sortParam = "reportedOn";

Order order = (searchRequest.isAscending())
  ? builder.desc(builder.neg(root.get(sortParam)))
  : builder.desc(root.get(sortParam));

query.orderBy(order);

基本上 ORDER BY -reported_on DESCORDER BY reported_on ASC 做同样的事情,但它将具有 NULL reported_on 值的记录一直排序到搜索结果的底部,即NULLS LAST 应该做什么。