ORDER BY in Criteria API 用于计算列名称(按别名)
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));
现在,如何根据标准 API 进行排序。
- 如果我使用 orderby root.CARD_NUM,该属性不存在于 Root 中。- 抛出异常。
- 如果我按 caseSelect 表达式本身排序,它会抛出错误
说明 CARD_ID 不在查询的 SELECTED 部分。
- 我不能在 select 表达式中包含 card_num / card_id,这不适合查询。
有什么方法可以只按别名排序吗?我看到 Order 是 Expression 类型,以及如何从字符串名称中获取表达式。我猜你可以在 Hibernate 中做到这一点。无论如何都可以在标准 API 中使用休眠 orderby 吗?猜个傻q
感谢任何帮助。
JPA 标准 API 似乎无法做到这一点,您将不得不退而求其次,改为使用 JPQL/HQL。
这是不可能的,感觉就像是 JPA 遗漏了一个案例。
虽然如果使用休眠 API 是可能的。但是,我的解决方法是 -
- 创建了一个包含 case 表达式的视图。
- 用我的实体加入视图(你不能加入,但是再加入一个
query.from(View.class)).
- 在where中添加视图和实体的id。
现在在顺序中您可以通过 View.column_name 提及列名称。
使用条件 API,您需要按 caseSelect
表达式排序。我试了一下,它在 Hibernate 5.4 上运行良好。您使用哪个版本?
我遇到过类似的情况...
query.multiselect(root, computedColumn);
query.orderBy(new Order[]{filterDTO.getSortAsc() ? cb.asc(cb.literal(2)) : cb.desc(cb.literal(2))});
我的情况是 computedColumn 是子查询...我没有设法让它按列别名工作,但它似乎按元组中返回的列索引工作,所以我猜在你的代码中它应该按索引 1
query.orderBy(cb.asc(cb.literal(1)));
遇到我的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));
现在,如何根据标准 API 进行排序。
- 如果我使用 orderby root.CARD_NUM,该属性不存在于 Root 中。- 抛出异常。
- 如果我按 caseSelect 表达式本身排序,它会抛出错误 说明 CARD_ID 不在查询的 SELECTED 部分。
- 我不能在 select 表达式中包含 card_num / card_id,这不适合查询。
有什么方法可以只按别名排序吗?我看到 Order 是 Expression 类型,以及如何从字符串名称中获取表达式。我猜你可以在 Hibernate 中做到这一点。无论如何都可以在标准 API 中使用休眠 orderby 吗?猜个傻q
感谢任何帮助。
JPA 标准 API 似乎无法做到这一点,您将不得不退而求其次,改为使用 JPQL/HQL。
这是不可能的,感觉就像是 JPA 遗漏了一个案例。 虽然如果使用休眠 API 是可能的。但是,我的解决方法是 -
- 创建了一个包含 case 表达式的视图。
- 用我的实体加入视图(你不能加入,但是再加入一个 query.from(View.class)).
- 在where中添加视图和实体的id。
现在在顺序中您可以通过 View.column_name 提及列名称。
使用条件 API,您需要按 caseSelect
表达式排序。我试了一下,它在 Hibernate 5.4 上运行良好。您使用哪个版本?
我遇到过类似的情况...
query.multiselect(root, computedColumn);
query.orderBy(new Order[]{filterDTO.getSortAsc() ? cb.asc(cb.literal(2)) : cb.desc(cb.literal(2))});
我的情况是 computedColumn 是子查询...我没有设法让它按列别名工作,但它似乎按元组中返回的列索引工作,所以我猜在你的代码中它应该按索引 1
query.orderBy(cb.asc(cb.literal(1)));