升级Jakarta Persistence 3.2.0后LIKE查询谓词失效问题求助
问题原因分析
Jakarta Persistence 3.2.0对LIKE谓词的转义字符处理做了隐性变更:当调用cb.like(expr, value)不带转义参数时,规范实现会自动添加escape ''(空转义字符)。而部分数据库(比如MySQL)在处理空转义字符时,会改变原本的匹配逻辑——原本'bar'能正常匹配'bar',但带escape ''后,数据库会将空字符视为转义符,导致匹配规则异常,无法检索到目标数据。
替代解决方案
针对这个问题,有几种可行的修复方式:
- 显式指定转义字符
调用cb.like的重载方法,指定一个不会干扰业务的转义字符(比如\,Java中需转义为\\),这样就不会生成escape '':
Specification<MyEntity> byFoo() { return (root, query, cb) -> cb.like( root.get(MyEntity_.FOO), Specifications.like("bar"), '\\' // 显式指定转义字符 ); }
- 改用
likeIgnoreCase(适配不区分大小写场景)
如果业务允许不区分大小写匹配,可以直接用cb.likeIgnoreCase,该方法在3.2.0版本中不会自动添加空转义字符:
Specification<MyEntity> byFoo() { return (root, query, cb) -> cb.likeIgnoreCase( root.get(MyEntity_.FOO), Specifications.like("bar") ); }
自定义匹配规则,规避默认转义逻辑
如果不需要转义功能,可根据业务场景直接构建匹配逻辑:- 全匹配(无通配符)时,直接用
equal替代like:Specification<MyEntity> byFoo() { return (root, query, cb) -> cb.equal( root.get(MyEntity_.FOO), "bar" ); } - 需要通配符时,手动拼接匹配串后显式指定转义字符:
Specification<MyEntity> byFooWithWildcard() { String pattern = "%" + "bar" + "%"; return (root, query, cb) -> cb.like( root.get(MyEntity_.FOO), pattern, '\\' ); }
- 全匹配(无通配符)时,直接用
检查
Specifications.like方法实现
确认你的Specifications.like方法是否已在生成匹配字符串时处理了转义逻辑,若已处理,配合显式指定的转义字符即可恢复正常匹配。
内容的提问来源于stack exchange,提问作者Mena
相关产品推荐
相关产品推荐

