Spring Boot 3中JPA含分号查询分页失效问题求助
Spring Boot 3 JPA原生查询分页时分号解析异常问题
问题背景
在Spring Boot 3中编写带分号的JPA原生查询,示例代码如下:
@Query(value=".... LIKE CONCAT(?, '%;') ...")
最终生成的SQL会被错误改写为:
LIKE CONCAT(?, '% limit ?;')
尝试用反斜杠转义分号无效,但相同代码在Spring Boot 2.7中可正常运行。
补充测试场景:
- 返回
List的普通查询能正常执行:
@Query(value = "SELECT u.* FROM user u WHERE u.userId LIKE CONCAT(?1, '%;') OR u.userId IN ?2", nativeQuery = true) List<UserEntity> search(String search, List<String> userIds);
- 改为返回
Page并添加Pageable分页参数后,查询直接失败。
问题原因
Spring Boot 3配套升级了Hibernate至6.x版本,Hibernate 6.x对原生查询的SQL解析逻辑做了调整:当处理带分页的原生查询时,框架会自动拼接limit/offset语句,但解析器会误将查询字符串中的';'识别为SQL语句的结束标记,导致把%;拆分为%和;,进而错误地将分页的limit插入到CONCAT语句中间,破坏了原有的拼接逻辑。
而Spring Boot 2.7使用的Hibernate 5.x版本不存在该解析问题,因此旧版本中代码可正常运行。
解决办法
以下是几种可行的解决方案:
1. 将分号作为参数传入
避免在原生SQL中硬写';',把它作为单独参数传递:
@Query(value = "SELECT u.* FROM user u WHERE u.userId LIKE CONCAT(?1, ?2) OR u.userId IN ?3", nativeQuery = true) Page<UserEntity> search(String search, String suffix, List<String> userIds, Pageable pageable);
调用时传入suffix = ";"即可,这样解析器不会把分号当成语句结束符。
2. 手动指定count查询
分页查询时JPA会自动生成count统计查询,手动指定count查询可强制Hibernate分别解析主查询和count查询,避免解析错误:
@Query( value = "SELECT u.* FROM user u WHERE u.userId LIKE CONCAT(?1, '%;') OR u.userId IN ?2", countQuery = "SELECT COUNT(*) FROM user u WHERE u.userId LIKE CONCAT(?1, '%;') OR u.userId IN ?2", nativeQuery = true ) Page<UserEntity> search(String search, List<String> userIds, Pageable pageable);
3. 用ASCII码替代分号(数据库兼容方案)
针对支持ASCII函数的数据库(如MySQL、PostgreSQL),用CHAR(59)代替直接写';'(59是分号的ASCII编码):
@Query(value = "SELECT u.* FROM user u WHERE u.userId LIKE CONCAT(?1, '%', CHAR(59)) OR u.userId IN ?2", nativeQuery = true) Page<UserEntity> search(String search, List<String> userIds, Pageable pageable);
内容的提问来源于stack exchange,提问作者Hany Sakr
相关产品推荐
相关产品推荐

