MyBatis Plus like参数为百分号%查询结果异常原因分析及解决

 更新时间:2025年09月25日 09:03:34   作者:_院长大人_  
文章指出在MyBatisPlus使用LIKE查询时,用户输入的%可能导致通配符误匹配,推荐使用ESCAPE转义功能,将%转换为普通字符,既支持模糊查询又避免全表匹配,提升准确性和性能

在日常开发中,我们经常使用 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.hasText(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. 查询数据量过大,影响系统性能。
  2. 业务逻辑错误,返回了不相关的数据。

解决方案

方法 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("%", "").trim() : null;

queryWrapper
.like(StringUtils.hasText(plateNumber), HlCar::getPlateNumber, plateNumber)
.like(StringUtils.hasText(vin), HlCar::getVin, vin)
.like(StringUtils.hasText(modelName), HlCar::getCarSeries, modelName);

缺点

  • 如果用户查询 "100%ABC",会变成 "100ABC",查询结果不准确。
  • 失去了 % 作为普通字符的意义,不能搜索包含 % 的数据。

方法 2:使用eq()进行精确匹配(适用于完全匹配查询)

如果 plateNumber 是用户完整输入的车牌号,VIN 码和 车型名 也是完整的,则可以使用 eq()

queryWrapper.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

优点

  • 支持模糊查询,但不会误匹配。
  • 不会影响查询数据的完整性,能够正确匹配包含 % 的车牌号或 VIN。

修改后执行结果

  • 可以看到查询正常了
  • 在这里插入图片描述


最佳实践推荐

方法适用场景是否支持 %
作为普通字符
是否支持模糊匹配
方法 1:去掉%适用于只需要模糊查询的情况❌(去掉 %
影响查询结果)
方法 2:用 eq()
精确匹配
适用于 VIN 码、完整车牌匹配
方法 3:用 ESCAPE
转义(推荐)
适用于所有 LIKE 查询

综合来看,方法 3(使用 ESCAPE)是最优解,兼顾了模糊匹配和 % 作为普通字符的问题。

总结

在 MyBatis Plus LIKE 查询时,如果 plateNumbervinmodelName 含有 %,会导致误匹配。

直接 LIKE '%' 会查询所有数据,可能影响业务逻辑。

解决方案:

  1. 去掉 %(不推荐)
  2. 改用 eq() 精确匹配(适用于完整匹配)
  3. 使用 ESCAPE 转义 %(推荐)

正确使用 LIKE 查询,能避免数据误匹配,提高查询准确性和系统性能!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java中的输出格式化问题小结

    Java中的输出格式化问题小结

    在Java中,System.out.printf方法用于格式化输出,格式化字符串`%.6f`表示浮点数保留6位小数,其他格式化选项包括`%d`(整数)、`%s`(字符串)和`%e`(科学计数法),示例代码展示了如何使用这些格式化选项,感兴趣的朋友一起看看吧
    2025-02-02
  • java的GUI实现简单切换界面

    java的GUI实现简单切换界面

    这篇文章主要为大家详细介绍了java的GUI实现简单切换界面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • Java中synchronized关键字的使用和原理详解

    Java中synchronized关键字的使用和原理详解

    这篇文章主要介绍了Java中synchronized关键字的使用和原理详解,JVM 是通过进入、退出 对象监视器(Monitor)来实现对方法、同步块的同步的,而对象监视器的本质依赖于底层操作系统的互斥锁实现,需要的朋友可以参考下
    2023-09-09
  • springboot集成camunda的实现示例

    springboot集成camunda的实现示例

    本文主要介绍了springboot集成camunda的实现示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • MyBatis的模糊查询mapper.xml的写法讲解

    MyBatis的模糊查询mapper.xml的写法讲解

    这篇文章主要介绍了MyBatis的模糊查询mapper.xml的写法讲解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • WebService的相关概念

    WebService的相关概念

    这篇文章主要介绍了WebService的相关概念的相关资料,需要的朋友可以参考下
    2017-10-10
  • Java中List根据条件删除元素的几种方式

    Java中List根据条件删除元素的几种方式

    java List删除指定元素有四种方法,分别是普通for循环,增强for循环,CopyOnWriteArrayList以及原生的Iterator迭代器循环来删除list中指定的某个元素,非常的简单,并通过代码示例讲解的非常详细,需要的朋友可以参考下
    2024-04-04
  • 简单了解Java方法的定义和使用实现

    简单了解Java方法的定义和使用实现

    这篇文章主要给大家介绍了关于Java中方法使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • springboot2升级到springboot3过程相关修改记录

    springboot2升级到springboot3过程相关修改记录

    本文详细记录了将Spring Boot 2升级到Spring Boot 3的过程,包括升级JDK到17、修改依赖、配置文件调整以及处理一些特定问题,如Redisson版本升级和Swagger配置,感兴趣的朋友跟随小编一起看看吧
    2024-12-12
  • Mybatis如何开启控制台打印sql语句

    Mybatis如何开启控制台打印sql语句

    在SpringBoot与Mybatis整合开发中,开启控制台SQL语句打印是一个常见需求,有助于调试与性能优化,方法一:在Mybatis配置文件mybatis-config.xml中添加设置;方法二:在SpringBoot配置文件application.yml或properties中
    2024-11-11

最新评论