大家好,我是小米,一枚31岁的技术小太阳,从业多年,见惯了代码里那些"表面无害,实则藏雷"的小细节。今天就给大家分享一个很多人在 MyBatis 模糊查询 中会踩的坑,也是我上周面试候选人时提问的一道经典问题。
故事,从一个"奇怪"的Bug说起
前不久我们团队在做商品管理后台系统改造,有个老同事灰常熟练地提交了一个 PR,功能是"模糊搜索商品名称"。需求很简单,比如输入"手机",就能匹配"苹果手机""小米手机""华为手机壳"这种。
很快,他写完代码,提测上线。我心里想着,这种 CRUD 小功能还能出啥岔子?结果当天晚上就接到了 QA 的反馈电话:
"小米,奇怪了,'手机'两个字搜不到'小米手机',你帮忙看下?"
我心里咯噔一下,立马连夜打开了代码。
看似没毛病的代码,却查不出来?
点开 mapper.xml,一行熟悉的 SQL 出现在眼前:
你是不是也觉得没毛病?我当年刚学 MyBatis 时也会这么写。但问题就出在这个 '%#{name}%' 上。你以为这会拼成 '%手机%',实际上拼成了什么呢?
我们打印了真实的 SQL 日志,一看------直接傻眼了:
问号代表的是预编译参数,结果数据库收到的命令是:
它根本不是你想象的 name LIKE '%手机%'。怪不得查不出来!
MyBatis 模糊查询的正确写法
有两种正确方式,我总结给你
方式一:用 CONCAT 拼接
这种方式等价于 SQL 中的:
优点:占位符保持预编译优势,不容易被 SQL 注入,性能更安全。
方式二:Java 代码中拼接 %,传入参数
比如在 Service 或 Controller 层这么写:
然后传给 mapper:
这种方式也能成功模糊查询,但缺点是:你在 Java 层拼接了字符串,如果多个字段都要模糊匹配,拼接过程容易出错,还可能有注入风险。
所以到底选哪种方式更推荐?
我个人强烈建议:使用第一种 CONCAT 拼接的方式。
不仅写法清晰、安全,而且在后期调试 SQL 时更容易定位问题。不信你问问 DBA 们,哪个更好维护?他们一定告诉你,SQL 的参数尽量保持预编译形式。
进阶拓展:MyBatis Plus 怎么搞?
我知道你肯定在用 MyBatis Plus,那我们再说说用 MP 的方式怎么写模糊查询。
方法一:使用 like 条件构造器
MyBatis Plus 会自动帮你拼成:
就是这么贴心!
方法二:使用 Lambda 表达式(更优雅)
不仅 IDE 自动补全字段名,不怕写错,而且性能更佳,更利于代码重构。
踩坑合集:这些写法别再用了!
下面是一些常见错误示例,小米帮你挨个拆雷:
面试官视角:我为什么喜欢问这个问题?
这个问题看似简单,其实能体现很多候选人是否"脚踏实地做过项目"。我最常听到的回答是:
"啊,我都是 copy 之前的写法,还真没注意过原理......"
但如果一个候选人告诉我:
"我知道不能直接用 %#{name}%,我一般用 CONCAT,或者在 Java 里拼接 %,不过我更推荐在 SQL 层处理。"
那我心里直接给他加 20 分!
小结:一口气掌握模糊查询的正确姿势
总结一下:
- 不推荐: '%#{param}%'
- 推荐一: LIKE CONCAT('%', #{param}, '%')
- 推荐二: Java 拼接 %param% 再传参
- 更推荐: MyBatis Plus 的 .like() 和 .lambdaQuery()
- 注意 SQL 注入、防止错误转义
聊点题外话:写业务代码也能体现技术深度
很多人觉得做业务代码没技术含量,其实不是的,像模糊查询这种小细节背后就隐藏着对预编译、安全性、SQL 执行效率的理解。
一个优秀的工程师,不在于能不能写出"很炫的算法",而在于能不能把每一个 "简单"的功能做到极致。
END
如果你也曾因为模糊查询写错被批评、被查 Bug 查到秃头,不要自责,踩坑是成长最快的方式!
这篇文章,如果对你有帮助,欢迎点个 "在看" 或 "转发给你的队友" ------别让他也踩坑啦~
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号"软件求生",获取更多技术干货!
咱们下期见!