news 2026/6/26 15:25:55

2026年了,还在手写SQL?我整理了5个让MyBatis-plus失效的场景。

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
2026年了,还在手写SQL?我整理了5个让MyBatis-plus失效的场景。

团队去年全面切MyBatis-plus,想着CRUD不用写了,效率翻倍。结果半年后,复杂业务场景里还是手写SQL,而且比原来更绕。整理了5个让MyBatis-plus"失效"的场景,不是框架不好,是用错了地方。

场景一:多层嵌套子查询

MyBatis-plus的QueryWrapper链式调用,两层嵌套还能看,三层以上就是灾难

// 两层勉强能读 queryWrapper.eq("status",1).in("id", new QueryWrapper<Order>().select("user_id").eq("amount",100));// 三层?我放弃了,直接写XML

实际业务:查"最近30天消费超过500元且购买过指定品类且退货率低于10%的用户"。三层子查询+聚合+条件,QueryWrapper写出来像天书,维护的人骂娘。

手写SQL:

<selectid="findQualifiedUsers"resultType="User">SELECT u.* FROM user u WHERE u.id IN(SELECT o.user_id FROM`order`o WHERE o.create_time>DATE_SUB(NOW(), INTERVAL30DAY)AND o.amount>500AND o.id IN(SELECT oi.order_id FROM order_item oi WHERE oi.category_id=#{categoryId})AND o.user_id NOT IN(SELECT r.user_id FROM refund r WHERE r.rate>0.1))</select>

看着长,但结构清晰,SQL优化器也能看懂。MyBatis-plus生成的SQL,三层嵌套后逻辑混乱,执行计划全表扫描。

场景二:动态表名/动态列

分库分表场景,表名按月份拆分: order_202601 、 order_202602 。

MyBatis-plus的 @TableName 注解不支持动态表名,除非自己写拦截器替换SQL,但那样还不如直接写XML。

<selectid="statReport"resultType="Map">SELECT province, city, channel, DATE(create_time)as dt, COUNT(*)as order_cnt, SUM(amount)as total_amount, AVG(amount)as avg_amount, SUM(CASE WHENstatus=9THEN1ELSE0END)/COUNT(*)as refund_rate FROM`order`<where><iftest="province != null">AND province=#{province}</if><iftest="startDate != null">AND create_time>=#{startDate}</if></where>GROUP BY province, city, channel, DATE(create_time)WITH ROLLUP</select>

WITH ROLLUP 做维度汇总,MyBatis-plus不支持这种语法,只能原生SQL。

场景四:批量插入优化

MyBatis-plus的 saveBatch 默认是一条条INSERT,批量1000条数据,数据库往返1000次。

// 默认实现,性能极差 userService.saveBatch(userList);//1000次网络往返

想优化?自己写 INSERT INTO … VALUES (…), (…), (…) ,或者配置 rewriteBatchedStatements=true ,但MyBatis-plus不帮你做这个。

手写SQL:

<insertid="batchInsert">INSERT INTO user(name, email, create_time)VALUES<foreachcollection="list"item="item"separator=",">(#{item.name}, #{item.email}, NOW())</foreach></insert>

一次网络往返,性能提升100倍。

场景五:数据库特定语法

MySQL的 ON DUPLICATE KEY UPDATE 、PostgreSQL的 ON CONFLICT 、SQL Server的 MERGE ,MyBatis-plus的通用CRUD不支持这些方言。

<insertid="upsert">INSERT INTO user(id, name, email)VALUES(#{id}, #{name}, #{email})ON DUPLICATE KEY UPDATE name=VALUES(name), email=VALUES(email), update_time=NOW()</insert>

我的用法
不是不用MyBatis-plus,是分层用:

简单CRUD、单表查询、快速原型:MyBatis-plus,省代码

复杂查询、子查询、聚合、批量、方言特性:手写XML,可控可优化

一个反直觉的结论

MyBatis-plus最大的价值,不是让你不写SQL,是让你明确知道哪些SQL不用写。简单场景省时间,复杂场景不折腾,边界清晰。
如果所有SQL都手写,和MyBatis有什么区别?如果所有SQL都用MyBatis-plus,复杂业务就是灾难。

最后说个数据

我们团队代码统计:MyBatis-plus占60%,手写XML占40%。但Bug率,手写XML的部分反而更低,因为复杂逻辑显式表达,review时容易发现问题。MyBatis-plus生成的SQL,有时候执行计划全表扫描,直到线上慢查询才发现。

工具是帮你省时间的,不是帮你思考的。复杂场景,手写SQL是负责任的选择。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 15:25:41

终极指南:用Deep3D将2D视频瞬间变成立体3D大片

终极指南&#xff1a;用Deep3D将2D视频瞬间变成立体3D大片 【免费下载链接】Deep3D Real-Time end-to-end 2D-to-3D Video Conversion, based on deep learning. 项目地址: https://gitcode.com/gh_mirrors/dee/Deep3D 你是否曾幻想过将手机里的普通家庭录像、旅行视频&…

作者头像 李华
网站建设 2026/6/26 15:23:49

企业级应用权限绕过漏洞剖析:从原理到实战复现

1. 项目概述&#xff1a;一次典型的企业级应用权限绕过漏洞分析最近在安全社区里&#xff0c;关于“亿赛通电子文档安全管理系统”的一个接口漏洞讨论得挺热。这个漏洞编号虽然还没进CVE&#xff0c;但业内通常称之为“LinkFilterService接口权限绕过漏洞”。简单来说&#xff…

作者头像 李华
网站建设 2026/6/26 15:20:36

宝可梦移动端存档编辑器PKHeX.Mobile:新手快速上手完整指南

宝可梦移动端存档编辑器PKHeX.Mobile&#xff1a;新手快速上手完整指南 【免费下载链接】PKHeX.Mobile Pokmon save editor for Android and iOS! 项目地址: https://gitcode.com/gh_mirrors/pk/PKHeX.Mobile 宝可梦训练家们&#xff0c;你是否曾经为培育一只完美宝可梦…

作者头像 李华
网站建设 2026/6/26 15:19:05

10分钟快速上手:RVC语音克隆与实时变声完整指南

10分钟快速上手&#xff1a;RVC语音克隆与实时变声完整指南 【免费下载链接】Retrieval-based-Voice-Conversion-WebUI Easily train a good VC model with voice data < 10 mins! 项目地址: https://gitcode.com/GitHub_Trending/re/Retrieval-based-Voice-Conversion-We…

作者头像 李华
网站建设 2026/6/26 15:17:51

VMware Unlocker终极指南:3分钟解锁macOS虚拟机隐藏功能

VMware Unlocker终极指南&#xff1a;3分钟解锁macOS虚拟机隐藏功能 【免费下载链接】unlocker VMware Workstation macOS 项目地址: https://gitcode.com/gh_mirrors/unloc/unlocker 想在Windows或Linux电脑上体验苹果macOS系统吗&#xff1f;VMware Workstation默认屏…

作者头像 李华