Hibernate 5.6中order by含<>表达式导致createQuery执行失败求助
Hibernate 5.6 CriteriaBuilder 自定义排序报错解决方案
问题场景
需要实现的原生SQL排序逻辑:
order by rmgtnav_path, rmgtnav_collection_type<>'PROFILE', rmgtnav_denotation asc
使用CriteriaBuilder编写的代码在调用session.createQuery(cq)时抛出QuerySyntaxException,错误原因是HQL不允许在order by子句中直接使用<>比较表达式作为排序项。
解决方案
1. 修复排序表达式语法错误
HQL不支持在order by中直接使用比较表达式,需用case when表达式替代原有的<>比较,实现相同排序逻辑:当rmgtnav_collection_type等于PROFILE时返回0,否则返回1,通过升序排序让PROFILE类型的记录排在最前面。
修改后的代码:
List<Order> orderStatements = new ArrayList<>(); // 按rmgtnav_path升序排序 orderStatements.add(cb.asc(root.get("rmgtnav_path"))); // 用case when实现rmgtnav_collection_type<>'PROFILE'的排序逻辑 Expression<Integer> profileOrder = cb.selectCase() .when(cb.equal(root.get("rmgtnav_collection_type"), "PROFILE"), 0) .otherwise(1); orderStatements.add(cb.asc(profileOrder)); // 按rmgtnav_denotation升序排序 orderStatements.add(cb.asc(root.get("rmgtnav_denotation"))); criteriQuery.orderBy(orderStatements); Query query = session.createQuery(cq);
2. 移除不必要的asc标签
HQL默认排序方向为升序,因此asc关键字可以省略。但CriteriaBuilder创建Order对象时必须显式指定排序方向,若要让生成的HQL中不出现多余的asc,可采取以下方式:
- 对于默认升序的排序项,可直接使用
Path接口的asc()方法,但Hibernate仍会生成asc关键字(不影响功能); - 若完全不想生成
asc,需改用原生SQL查询,或者接受asc存在(默认升序逻辑不受影响)。
原SQL中前两个排序项未显式写asc,第三个写了,因此可以仅对第三个排序项保留显式asc,前两个保持默认即可。
效果说明
通过case when转换后,生成的HQL语法合法,且完全匹配原SQL的排序逻辑:PROFILE类型记录排在最前面,后续按rmgtnav_path、rmgtnav_denotation升序排列。
内容的提问来源于stack exchange,提问作者d00d
相关产品推荐
相关产品推荐

