目录
- 问题分析
- 问题出现的情况
- 解决方案
- 方法 1:去除%,只匹配真实字符(不推荐)
- 方法 2:使用eq()进行精确匹配(适用于完全匹配查询)
- 方法 3:使用转义%(推荐本次使用)**
- Java 代码
- SQL 解析
- 修改后执行结果
- 最佳实践推荐
- 总结
在日常开发中,我们经常使用 MyBATis Plus 进行数据库查询。其中,LIKE 关键字用于模糊匹配,但如果用户输入的查询条件包含 %,可能会导致查询结果异常。
如下图,数据库里面是没有%的plate_number数据的,但是查询出86条数据

问题分析
我们来看一段 MyBatis Plus 的查询代码:
queryWrapper
.like(StringUtils.hasText(reqVo.getPlateNumber()), HlCar::getPlateNumber, reqVo.getPlateNumber())
.like(StringUtils.hasText(reqVo.getVin()), HlCar::getVin, reqVo.getVin())
.like(StringUtils.hasTextjs(reqVo.getModelName()), HlCar::getCarSeries, reqVo.getModelName());
该代码的意图是:
- 如果
reqVo.getPlateNumber()、reqVo.getVin()或reqVo.getModelName()非空,则执行LIKE查询。 - 例如,用户输入
"ABC",SQL 语句应为:
SELECT * FROM hl_car WHERE plate_number LIKE '%ABC%'
这样可以查询出包含 "ABC" 的所有车牌。
问题出现的情况
- 如果用户输入了
%,如"%",SQL 会变成:
SELECT * FROM hl_car WHERE plate_number LIKE '%%%'
由于 % 在 SQL LIKE 语句中是通配符,它会匹配任意字符,这可能导致匹配出比预期更多的数据。
- 如果用户仅输入
%,则LIKE '%%%'会匹配所有数据,完全失去筛选作用。
查询结果不符合预期,可能导致:
- 查询数据量过大,影响系统性能。
- 业务逻辑错误,返回了不相关的数据。
解决方案
方法 1:去除%,只匹配真实字符(不推荐)
一种简单的方式是移除 %,让 LIKE 只匹配实际输入的内容。
String plateNumber = reqVo.getPlateNumber() != null ? reqVo.getPlateNumber().replace("%", "").trim() : null;
String vin = reqVo.getVin() != null ? reqVo.getVin().replace("%", "").trim() : null;
String modelName = reqVo.getModelName() != null ? reqVo.getModelName().replace("%", ""http://www.devze.com).trim() : null;
queryWrapper
.like(StringUtils.hasText(plateNumber), HlCar::getPlateNumber, plateNumber)
.like(StringUtils.hasTe编程客栈xt(vin), HlCar::getVin, vin)
.like(StringUtils.hasText(modelName), HlCar::getCarSeries, modelName);
缺点:
- 如果用户查询
"100%ABC",会变成"100ABC",查询结果不准确。 - 失去了
%作为普通字符的意义,不能搜索包含%的数据。
方法 2:使用eq()进行精确匹配(适用于完全匹配查询)
如果 plateNumber 是用户完整输入的车牌号,VIN 码和 车型名 也是完整的,则可以使用 eq():
queryWwww.devze.comrapper.eq(StringUtils.hasText(plateNumber), HlCar::getPlateNumber, plateNumber) .eq(StringUtils.hasText(vin), HlCar::getVin, vin) .eq(StringUtils.hasText(modelName), HlCar::getCarSeries, modelName);
优点:
- 精准匹配,不会因为
%影响查询结果。 - 适用于 VIN 码、车牌号等完整匹配的查询。
缺点:
- 不能进行模糊匹配,用户必须输入完整的车牌号或 VIN 才能查到数据。
方法 3:使用转义%(推荐本次使用)**
将%和_使用escapeLike方法转义转义
Java 代码
// 处理 LIKE 查询参数,转义 % 和 _
String escapeLike(String str) {
return str != null ? str.replace("%", "\\%").replace("_", "\\_").trim() : null;
}
// 转义参数
String plateNumber = escapeLike(reqVo.getPlateNumber());
String vin = escapeLike(reqVo.getVin());
String modelName = escapeLike(reqVo.getModelName());
// 避免 `null` 参数
if (StringUtils.hasText(plateNumber)) {
queryWrapper.like(HlCar::getPlateNumber, plateNumber);
}
if (StringUtils.hasText(vin)) {
queryWrapper.like(HlCar::getVin, vin);
}
if (StringUtils.hasText(modelName)) {
queryWrapper.like(HlCar::getCarSeries, modelName);
}
SQL 解析
如果用户输入 "100%ABC",SQL 语句会变成:
SELECT * FROM hl_car WHERE plate_number LIKE '100\%ABC'
%让%变成普通字符,不再作为通配符。- 这样可以正确匹配
100%ABC,而不会匹配100XYZABC。
优点:
- 支持python模糊查询,但不会误匹配。
- 不会影响查询数据的完整性,能够正确匹配包含
%的车牌号或 VIN。
修改后执行结果
- 可以看到查询正常了
- 在这里插入图片描述


最佳实践推荐
| 方法 | 适用场景 | 是否支持 %作为普通字符 | 是否支持模糊匹配 |
|---|---|---|---|
| 方法 1:去掉% | 适用于只需要模糊查询的情况 | ❌(去掉 %影响查询结果) | ✅ |
| 方法 2:用 eq()精确匹配 | 适用于 VIN 码、完整车牌匹配 | ✅ | ❌ |
| 方法 3:用 ESCAPE转义(推荐) | 适用于所有 LIKE 查询 | ✅ | ✅ |
综合来看,方法 3(使用 ESCAPE)是最优解,兼顾了模糊匹配和 % 作为普通字符的问题。
总结
在 MyBatis Plus LIKE 查询时,如果 plateNumber、vin 或 modelName 含有 %,会导致误匹配。
直接 LIKE '%' 会查询所有数据,可能影响业务逻辑。
解决方案:
- 去掉
%(不推荐) - 改用
eq()精确匹配(适用于完整匹配) - 使用
ESCAPE转义%(推荐)
正确使用 LIKE 查询,能避免数据误匹配,提高查询准确性和系统性能!
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。
加载中,请稍侯......
精彩评论