【问题标题】:My custom order by in criteria query/jpql我在标准查询/jpql 中的自定义订单
【发布时间】:2019-09-12 09:26:59
【问题描述】:

是否可以通过在 Java 中使用条件查询或 jpql 来执行我的自定义订单?在我的表中,我有一个列 - 数字类型(目前,此列包括诸如123510 等数字)。我想按251103 的顺序对结果进行排序。

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<MyEntity> cq = cb.createQuery(MyEntity.class);
Root<MyEntity> root = cq.from(MyEntity.class);

cq.select(root);
cq.where(cb.equal(root.get("someMyFields"), "myExpectedFieldValue"));
cq.orderBy(cb.asc(root.get("myNumberField"))); // how can I sort result in this order 2, 5, 1, 10, 3?

TypedQuery<MyEntity> query = em.createQuery(cq);
query.setFirstResult(0);
query.setMaxResults(200);

return query.getResultList();

我该怎么做?

【问题讨论】:

  • 有什么逻辑?不解释就有点随意了
  • 无论有什么逻辑,方法 cb.asc() 都接受一个表达式,所以如果你在 `cb.asc()" 中实现你自己的逻辑,你应该能够完成你所要求的对于
  • 在前端,这些数字被赋值给字符串值(例如:2 - 'A', 5-'B', 1-'C', 10-'D', 3 -'D'。我只想按字母顺序对这些值进行排序。
  • 你能举个例子吗?

标签: java sql jpql criteria


【解决方案1】:

您必须在ORDER BY 子句中使用CASE 表达式来实现这种"sort indirection"。在 SQL 和 JPQL 中,这将是:

ORDER BY CASE myNumberField 
  WHEN 2  THEN 1
  WHEN 5  THEN 2
  WHEN 1  THEN 3
  WHEN 10 THEN 4
  WHEN 3  THEN 5
          ELSE 6
END

使用条件 API,使用 CriteriaBuilder.selectCase()

cq.orderBy(
  qb.selectCase(root.get("myNumberField"))
    .when(qb.literal(2), qb.literal(1))
    .when(qb.literal(5), qb.literal(2))
    .when(qb.literal(1), qb.literal(3))
    .when(qb.literal(10), qb.literal(4))
    .when(qb.literal(3), qb.literal(5))
    .otherwise(qb.literal(6))
    .getExpression()
    .asc());

当然,更好的解决方案是将这些值标准化到一个单独的表中,您可以将其加入仅用于排序:

SELECT *
FROM t
JOIN orderings o ON t.myNumberField = o.myNumberField
ORDER BY o.orderDefinition

【讨论】:

    【解决方案2】:

    您还可以通过在数据库 bean 中使用特殊字段来使用 CriteriaQuery 的自定义排序:

    // this is used for obtaining an arbitrary ordering by statuses
    @Formula(value="(CASE status\n" +
            "           WHEN 'DELETED'::text THEN 1\n" +
            "           WHEN 'UPDATED'::text THEN 2\n" +
            "           WHEN 'SUBMITTED'::text THEN 3\n" +
            "           ELSE 10\n" +
            "           END)")
    private int statusPriority;
    

    您可以通过 Pagination 对象将 statusPriority 用作常规排序字段。结果查询将包含以下内容:

    order by (CASE quotationv0_.status
               WHEN 'DELETED'::text THEN 1
               WHEN 'UPDATED'::text THEN 2
               WHEN 'SUBMITTED'::text THEN 3
               ELSE 10
               END) asc
    

    【讨论】:

      猜你喜欢
      • 2014-08-13
      • 2014-08-15
      • 2021-02-22
      • 2011-08-27
      • 2021-11-26
      • 1970-01-01
      • 2019-04-24
      • 2023-03-07
      • 2011-11-09
      相关资源
      最近更新 更多