Spring Boot从2.6.x升级到2.7.x后分页查询出现HQL语法错误
Spring Boot 2.7.x升级后JPA分页查询排序异常解决
问题分析
升级Spring Boot从2.6.x到2.7.x后,Spring Data JPA对@Query结合Pageable的排序解析逻辑发生变更,导致传入的分页排序规则被错误关联到子查询的Y实体上,而非主查询的X实体,触发Invalid path: 'y.name'的语法错误。另外你的查询语句存在笔误:WHERE子句里的t.status、t.fieldId应为x.status、x.fieldId(主实体别名为x),这会进一步干扰JPA的语句解析。
解决方案
1. 显式指定排序字段的实体别名
在@SortDefault中明确标注排序字段所属的主实体别名,避免JPA解析时混淆实体:
@RequestParam(value = "term", required = false) String term, @SortDefault(sort = "x.name", direction = Direction.ASC) Pageable pageable) { Page<SomeResult> results = findSome(..., pageable);
如果使用静态元模型,可通过alias参数指定实体:
@SortDefault(sort = X_.NAME, direction = Direction.ASC, alias = "x") Pageable pageable
2. 用countQuery分离分页逻辑
在@Query中显式定义countQuery,让分页计数与数据查询逻辑完全独立,防止排序规则渗透到子查询:
@Query(value = """ SELECT x FROM X x WHERE x.fieldId IN (:fieldIds) AND ((:statusList) IS NULL OR x.status IN (:statusList)) AND (:term IS NULL OR LOWER(x.name) LIKE :term OR LOWER(x.code) LIKE :term) AND (:excludeId IS NULL OR NOT EXISTS ( FROM Y y WHERE y.id.someId = x.id AND y.id.someOtherId = :excludeId ) ) """, countQuery = """ SELECT COUNT(x) FROM X x WHERE x.fieldId IN (:fieldIds) AND ((:statusList) IS NULL OR x.status IN (:statusList)) AND (:term IS NULL OR LOWER(x.name) LIKE :term OR LOWER(x.code) LIKE :term) AND (:excludeId IS NULL OR NOT EXISTS ( FROM Y y WHERE y.id.someId = x.id AND y.id.someOtherId = :excludeId ) ) """) Page<X> findSome(Set<Long> fieldIds, List<Status> statusList, String term, Long excludeId, Pageable pageable);
3. 升级Spring Boot补丁版本
该问题大概率是Spring Data JPA 2.7.x初期版本的解析bug,升级到2.7.10及以上的补丁版本,官方已修复此类排序解析异常。
4. 手动构造排序规则
放弃@SortDefault,在调用findSome时手动构造带实体别名的Sort对象:
Sort sort = Sort.by(Sort.Order.asc("x.name")); Pageable pageable = PageRequest.of(pageNum, pageSize, sort); Page<SomeResult> results = findSome(fieldIds, statusList, term, excludeId, pageable);
前置修正
先把查询语句中的t.全部替换为x.,修正实体别名的笔误,再执行上述方案,可快速解决问题。
内容的提问来源于stack exchange,提问作者ALex
相关产品推荐
相关产品推荐

