spring data jpa 的 specification 通过 criteriabuilder 的 like() 配合 concat() 或字符串拼接实现模糊查询,支持前缀、后缀、全模糊匹配;推荐用 lower() 统一转小写以保证跨库一致性,并注意防止 sql 注入。

Spring Data JPA 的 Specification 本身不直接支持 SQL 通配符(如 %、_),但你可以通过 CriteriaBuilder 的 like()、ilike()(PostgreSQL)或 lower()/upper() 配合字符串拼接,安全地构造带通配符的模糊查询。
用 like() + concat() 实现前后/左右模糊匹配
like() 是标准 JPA 方法,需手动拼接通配符。关键点是:通配符必须作为字符串值的一部分传入,不能写在字段名里;且推荐使用 CriteriaBuilder#concat() 或 Java 字符串拼接(注意防止 SQL 注入)。
- 前缀匹配(以 xxx 开头):
cb.like(root.get("name"), cb.concat(cb.literal("xxx"), "%")) - 后缀匹配(以 xxx 结尾):
cb.like(root.get("name"), cb.concat("%", cb.literal("xxx"))) - 全模糊(包含 xxx):
cb.like(root.get("name"), cb.concat("%", cb.concat(cb.literal("xxx"), "%"))) - 更简洁写法(Java 字符串拼接):
cb.like(root.get("name"), "%" + keyword + "%")—— 仅限 keyword 已校验/转义,否则有注入风险
大小写不敏感查询:用 lower() 统一转换
数据库默认 like 区分大小写(如 MySQL 默认不区分,但 H2/PostgreSQL 区分)。为确保跨库一致性,建议统一转小写:
cb.like(cb.lower(root.get("name")), "%" + keyword.toLowerCase() + "%")- 也可用
cb.equal(cb.lower(root.get("name")), keyword.toLowerCase())做精确小写匹配
组合多个 like 条件:用 and() / or() 连接
Specification 天然支持逻辑组合。例如“姓名或邮箱包含关键词”:
cb.or(cb.like(cb.lower(root.get("name")), "%" + kw + "%"),cb.like(cb.lower(root.get("email")), "%" + kw + "%"))
注意:多个 like 同时存在时,数据库可能无法有效使用索引,大数据量下建议配合全文检索或添加函数索引(如 PostgreSQL 的 LOWER(name) 索引)。
避免 SQL 注入:永远不要拼接用户输入到 like 模式中
keyword 若来自前端,需清理特殊通配符(%、_、)或设置 escape 字符:
- 禁用用户输入通配符:
keyword = keyword.replaceAll("[%_\\]", "") - 启用自定义 escape(如用
):cb.like(root.get("desc"), "%"+kw+"%", '\'),然后要求用户写abc%表示查字面量% - JPA 2.1+ 支持
escape()方法:cb.like(root.get("desc"), "\%" + kw, '\')
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











