按照 Criteria API 中计算列名的顺序 (通过别名) 排序。

huangapple go评论77阅读模式
英文:

ORDER BY in Criteria API for a computed column name (by alias)

问题

以下是翻译好的部分:

拥有一种情况其中我的 Java 代码对应于查询 -

      SELECT CUSTOMER_ID,
             CUSTOMER_NAME,
             CASE
                 WHEN COUNT (DISTINCT CARD_ID) > 1 THEN 'MULTIPLE'
                 ELSE MAX(CARD_NUM)
             END    AS CARD_NUM
        FROM CUSTOMER LEFT JOIN CARD ON CARD.CUSTOMER_ID = CUSTOMER.CUSTOMER_ID
    GROUP BY CUSTOMER_ID, CUSTOMER_NAME

用于详细信息的 Java 代码 -

    CriteriaBuilder cb = em.getCriteriaBuilder();
    final CriteriaQuery<Tuple> query = cb.createQuery(Tuple.class);
    final Root<Customer> root = query.from(Customer.class);
    Expression<Object> caseSelect = cb.selectCase()
    		.when(cb.greaterThan(cb.countDistinct(join.get(Card_.cardId)), 1L), "MULTIPLE")
    		.otherwise(cb.greatest(Card_.get(Card_.cardNum)));
    caseSelect.alias("card_num");
    selects.add(caseSelect);
    query.multiselect(selects).distinct(true);
    query.groupBy(exprs);
    query.orderBy(cb.asc(caseSelect));

现在如何在 Criteria API 中进行排序

1. 如果我按 root.CARD_NUM 进行排序该属性不在 Root 中- 抛出异常
2. 如果我只对 caseSelect 表达式进行排序它会抛出错误指出 CARD_ID 不在查询的选择部分中
3. 我不能在选择表达式中使用 card_num / card_id对于查询来说这是不正确的

有没有办法只按别名排序我看到 Order 是 Expression 类型如何从字符串名称获取表达式我猜在 Hibernate 中可以做到这一点无论如何在 Criteria API 中使用 Hibernate 的 orderby 是否可能猜一个愚蠢的问题

非常感谢您的帮助
英文:

Having a situation where my java code is symbolic to query -

  SELECT CUSTOMER_ID,
CUSTOMER_NAME,
CASE
WHEN COUNT (DISTINCT CARD_ID) &gt; 1 THEN &#39;MULTIPLE&#39;
ELSE MAX(CARD_NUM)
END    AS CARD_NUM
FROM CUSTOMER LEFT JOIN CARD ON CARD.CUSTOMER_ID = CUSTOMER.CUSTOMER_ID
GROUP BY CUSTOMER_ID, CUSTOMER_NAME

Java code for detailed info -

CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery&lt;Tuple&gt; query = cb.createQuery(Tuple.class);
final Root&lt;Customer&gt; root = query.from(Customer.class);
Expression&lt;Object&gt; caseSelect = cb.selectCase()
.when(cb.greaterThan(cb.countDistinct(join.get(Card_.cardId)), 1L), &quot;MULTIPLE&quot;)
.otherwise(cb.greatest(Card_.get(Card_.cardNum)));
caseSelect.alias(&quot;card_num&quot;);
selects.add(caseSelect);
query.multiselect(selects).distinct(true);
query.groupBy(exprs);
query.orderBy(cb.asc(caseSelect));

Now, how to do the order by in Criteria API.

  1. If I do orderby root.CARD_NUM, the attribute is not present in Root.- Throws exception.
  2. If I do order by the caseSelect expression itself it throws an error
    stating CARD_ID is not in SELECTED part of query.
  3. I cannot have card_num / card_id in select expression, that is not right for the query.

Any way to just order by Alias name? I see Order is Expression type, and how to get an expression from string name. I guess you can do this in Hibernate. Would it be possible to use hibernate orderby in criteria API anyways ? Guess a stupid q

Any help is appreciated.

答案1

得分: 4

我面对过类似的情况...

query.multiselect(root, computedColumn);
query.orderBy(new Order[]{filterDTO.getSortAsc() ? cb.asc(cb.literal(2)) : cb.desc(cb.literal(2))});

在我的情况下,computedColumn 是一个 Subquery... 我没有成功地通过列别名使其工作,但似乎可以通过元组中返回的列索引来使其工作,所以我想在你的代码中,它应该通过索引 1 来工作。

query.orderBy(cb.asc(cb.literal(1)));
英文:

I faced a similar situation...

query.multiselect(root, computedColumn);
query.orderBy(new Order[]{filterDTO.getSortAsc() ? cb.asc(cb.literal(2)) : cb.desc(cb.literal(2))});

I my case computedColumn is Subquery<String>...I did not manage to make it work by column alias but it seems to work by column index returned in the tupple so I guess in your code it should work by index 1

query.orderBy(cb.asc(cb.literal(1)));

答案2

得分: 2

利用 Criteria API,你需要按 caseSelect 表达式进行排序。我尝试过了,在 Hibernate 5.4 中可以正常工作。你使用的是哪个版本?

英文:

Using the Criteria API, you need to order by the caseSelect expression. I gave it a try and it works fine with Hibernate 5.4. Which version do you use?

答案3

得分: 1

似乎在JPA Criteria API中无法实现这一点,您将不得不回退到使用JPQL/HQL。

英文:

It seems this is not possible with the JPA Criteria API and you will have to fallback to using JPQL/HQL instead.

答案4

得分: 0

这几乎是不可能的,而且感觉就像是 JPA 漏掉的一个案例。
虽然如果使用 Hibernate API,是有可能的。但是,我的解决方法是:

  1. 创建一个包含 case 表达式的视图。
  2. 将该视图与我的实体进行连接(你不能直接进行连接,但可以再执行一个查询从 View.class 中获取数据)。
  3. 在 WHERE 子句中添加视图和实体的 ID。

现在在 ORDER BY 子句中,你可以按照 View.column_name 指定列名。

英文:

This is fairly not possible and just feels like a case missed by JPA.
Though if using hibernate API it is possible. But, my workaround was -

  1. Created a view which would contain the case expression.
  2. Join the view with my entity (you cannot do a join, but one more
    query.from(View.class)).
  3. In the where add the ids of View and the entity.

Now in the order by you could mention the column name by View.column_name.

huangapple
  • 本文由 发表于 2020年7月25日 08:13:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/63082972.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定