You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hibernate-JPA:如何向CriteriaBuilder查询传递含下划线的字符串?

解决CriteriaBuilder按LISTAGG生成字段排序的问题

核心问题原因

Hibernate对排序字段的字符串解析会把下划线当作分隔符,自动截断别名(比如col_12_0_会被识别为col),而自动生成的查询别名(如col_1_0_)本身带下划线,导致排序失效。另外PhysicalNamingStrategyStandardImpl负责的是实体与数据库列的命名映射,和查询时的动态别名无关,所以修改它没用。

可行解决方案

1. 自定义别名+手动绑定排序逻辑

不要依赖Hibernate自动生成的带下划线别名,给LISTAGG表达式指定不含下划线的自定义别名,然后在处理Pageable排序时,手动将排序字段映射到该表达式:

// 1. 构建LISTAGG表达式并指定自定义别名(避免下划线)
Expression<String> aggregatedField = cb.function(
    "LISTAGG",
    String.class,
    root.get("yourEntityProperty"), // 要聚合的实体属性
    cb.literal(", ") // 分隔符
).alias("aggregated_field"); // 自定义别名,无下划线

// 2. 将该表达式加入查询的select列表
criteriaQuery.select(cb.construct(YourResultDto.class, root.get("id"), aggregatedField));

// 3. 处理Pageable的排序,替换为对应表达式的排序
Sort originalSort = pageable.getSort();
List<Order> criteriaOrders = new ArrayList<>();

for (Sort.Order order : originalSort) {
    if ("aggregated_field".equals(order.getProperty())) {
        // 直接引用LISTAGG表达式进行排序,跳过Hibernate的字符串解析
        criteriaOrders.add(order.isAscending() ? cb.asc(aggregatedField) : cb.desc(aggregatedField));
    } else {
        // 普通实体属性按原有逻辑排序
        criteriaOrders.add(order.isAscending() ? cb.asc(root.get(order.getProperty())) : cb.desc(root.get(order.getProperty())));
    }
}

criteriaQuery.orderBy(criteriaOrders);

2. 直接使用表达式排序(无需别名)

如果不需要在返回结果中暴露别名,可以直接跳过别名,在排序时直接引用LISTAGG的表达式对象:

Expression<String> listAggExpr = cb.function(
    "LISTAGG",
    String.class,
    root.get("yourEntityProperty"),
    cb.literal(", ")
);

// 加入select列表
criteriaQuery.select(cb.construct(YourResultDto.class, root.get("id"), listAggExpr));

// 直接用表达式排序(可根据Pageable动态生成升/降序)
criteriaQuery.orderBy(cb.desc(listAggExpr));

关键注意点

  • 避免使用带下划线的自定义别名,防止Hibernate的排序解析逻辑截断字段名
  • 不要依赖字符串形式的别名进行排序,直接引用表达式对象可以彻底绕开Hibernate的别名解析问题

内容的提问来源于stack exchange,提问作者Arturillo Smeriglia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 22:30:52