2126 字
约 7 分钟
14
MyBatis-Plus SQL 注入器是什么?一篇文章带你彻底搞懂!

MyBatis-Plus SQL 注入器是什么?一篇文章带你彻底搞懂!

前言

第一次看到 SQL 注入器(SQL Injector) 这个名字的时候,我直接懵了。

心里第一反应就是:

SQL 注入?不是黑客攻击吗?

后来才发现,MyBatis-Plus 的 SQL 注入器和 SQL 注入攻击没有半毛钱关系!

很多人学 MyBatis-Plus 时,一看到官方文档里的 ISqlInjectorDefaultSqlInjectorAbstractMethod,就开始照着敲代码。

结果代码敲完了,还是不知道:

  • SQL 注入器到底是什么?
  • 为什么要有 SQL 注入器?
  • 什么时候才会用到它?
  • 为什么平时开发几乎见不到它?

今天这篇文章,就带大家彻底搞懂 MyBatis-Plus SQL 注入器。


一、先说结论

SQL 注入器只有一句话:

它负责给 Mapper 批量添加通用 SQL 方法。

注意几个关键词:

  • 批量
  • 通用
  • SQL 方法

千万不要理解成:

动态生成 SQL。

它真正做的是:

Mapper
      ↓
SQL Injector
      ↓
注册 SQL 方法
      ↓
Mapper 可以直接调用

二、先看看没有 MyBatis-Plus 的时代

以前 MyBatis 是这样写的。

Mapper:

public interface UserMapper {

    User selectById(Long id);

}

然后 XML:

<select id="selectById">

SELECT *

FROM user

WHERE id = #{id}

</select>

每一个方法:

都需要:

Mapper

+

XML

全部自己写。


后来 MyBatis-Plus 出现了。

你突然发现:

userMapper.selectById(1L);

userMapper.insert(user);

userMapper.deleteById(1L);

userMapper.updateById(user);

这些方法:

居然不用写 XML!

很多人第一次都会问:

这些 SQL 到底是谁写的?

答案就是:

MyBatis-Plus 自己帮你注入进去的。

例如:

userMapper.selectById(id);

底层其实执行:

SELECT *

FROM user

WHERE id = ?

但是:

你根本没有写 XML。

为什么?

因为:

BaseMapper
      │
      ▼
SQL Injector
      │
      ▼
注册 SQL

项目启动的时候:

MyBatis-Plus 已经偷偷把这些 SQL 注册好了。


三、为什么叫"SQL 注入器"?

这里很多人都会误会。

SQL 注入器:

不是:

SQL Injection Attack

而是:

Inject SQL

什么意思?

就是:

把 SQL 方法注入到 Mapper 中。

例如:

你定义:

public interface UserMapper
        extends BaseMapper<UserDO>{
}

你并没有写:

selectById()

insert()

deleteById()

但是:

启动以后:

实际上:

UserMapper

↓

selectById()

insert()

delete()

update()

selectList()

...

全部都有了。

这些:

就是 SQL Injector 注进去的。

所以:

这里:

注入

不是:

攻击。

而是:

注册。


四、为什么需要 SQL 注入器?

先来看一个例子。

假设公司有:

User

Order

Article

Comment

Category

Product

六张表。

领导突然说:

以后所有表:

都要支持:

deleteAll();

例如:

userMapper.deleteAll();

orderMapper.deleteAll();

articleMapper.deleteAll();

怎么办?

最普通的方法:

每个 Mapper:

写:

int deleteAll();

然后:

每个 XML:

写:

DELETE FROM xxx

例如:

User:

DELETE FROM user

Order:

DELETE FROM order

Article:

DELETE FROM article

......

是不是发现:

除了:

表名不同

其他:

全部一样。

这就是:

重复代码。


五、SQL 注入器就是解决重复 SQL

于是:

我们写:

一个:

DeleteAll

告诉 MyBatis-Plus:

以后:

凡是:

Mapper。

都自动拥有:

deleteAll();

底层:

根据当前 Mapper 对应的表:

自动生成:

例如:

User:

DELETE FROM user;

Order:

DELETE FROM order;

Article:

DELETE FROM article;

是不是:

一下子舒服了。

这就是:

SQL 注入器最大的作用:

把重复 SQL 抽出来,一次编写,多处使用。


六、SQL 注入器什么时候才会用?

这是很多人最关心的问题。

答案:

绝大多数项目,你根本不会写 SQL 注入器。

因为:

MyBatis-Plus 已经帮你注入好了:

insert

deleteById

updateById

selectById

selectList

selectPage

这些:

已经够用了。

所以:

很多人:

用了三四年:

一次:

SQL 注入器:

都没写过。


七、什么时候需要自己写?

通常只有一种情况:

很多 Mapper 都需要同一个 SQL。

例如:

公司统一要求:

所有 Mapper:

都有:

insertBatch();

批量插入。

或者:

updateAllById();

批量更新。

或者:

physicalDeleteById();

物理删除。

这些:

所有 Mapper:

都需要。

如果:

每个 Mapper:

自己写。

每个 XML:

自己写。

维护成本:

非常高。

于是:

写一个:

SQL 注入器。

全部:

自动拥有。


八、什么时候不用 SQL 注入器?

例如:

只有:

UserMapper

需要:

selectVipUser();

那么:

直接:

Mapper:

List<User> selectVipUser();

XML:

<select>

SELECT *

FROM user

WHERE level='VIP'

</select>

结束。

根本:

不用:

SQL 注入器。

因为:

只有:

一个 Mapper:

会用。


九、SQL 注入器到底干了什么?

可以简单理解成:

项目启动的时候:

MyBatis-Plus:

开始扫描:

UserMapper

OrderMapper

ArticleMapper

发现:

UserMapper。

对应:

user

于是:

自动:

注册:

DELETE FROM user

发现:

OrderMapper。

对应:

order

于是:

注册:

DELETE FROM order

最后:

MyBatis:

里面:

多了一堆:

MappedStatement。

以后:

你调用:

userMapper.deleteAll();

其实:

就是执行:

对应:

DELETE FROM user;

整个过程:

可以画成:

Spring Boot 启动

        │

        ▼

扫描 Mapper

        │

        ▼

读取实体信息

        │

        ▼

SQL Injector

        │

        ▼

生成 SQL

        │

        ▼

注册到 MyBatis

        │

        ▼

Mapper 可以直接调用

十、SQL 注入器源码主要有三个角色

官方源码里面:

主要有三个类。

① BaseMapper

定义:

有哪些方法。

例如:

insert();

selectById();

updateById();

或者:

你新增:

deleteAll();

这里只是:

告诉 Java:

有这个方法。

但是:

没有 SQL。


② AbstractMethod

负责:

描述:

这个方法:

执行什么 SQL。

例如:

deleteAll()

↓

DELETE FROM 表名

以后:

无论:

User。

还是:

Order。

都是:

这里生成。


③ DefaultSqlInjector

负责:

把:

这些:

SQL 方法:

注册:

到:

MyBatis。

最终:

Mapper:

才能:

真正执行。

所以:

三者关系:

BaseMapper

定义方法

        │

        ▼

AbstractMethod

定义 SQL

        │

        ▼

DefaultSqlInjector

注册 SQL

        │

        ▼

Mapper 可以使用

十一、它和 MapStruct 有没有点像?

如果你刚学完:

MapStruct。

其实会发现:

它们思想:

非常像。

MapStruct:

把:

setName()

setAge()

setAvatar()

这些:

重复:

对象转换:

抽出来。

变成:

UserConvert.convert();

SQL 注入器:

把:

DELETE

UPDATE

INSERT

这些:

重复:

SQL:

抽出来。

变成:

统一:

注册。

是不是:

本质:

都是:

发现重复

↓

抽象

↓

统一管理

↓

统一复用

这其实就是:

软件设计里面:

非常经典的一种思想:

不要让重复代码到处出现,而是把公共能力集中起来。


十二、一个非常重要的误区

很多人学完 SQL 注入器。

以后:

所有 SQL:

都想:

写:

SQL 注入器。

其实:

完全没必要。

真正开发:

应该这样选择:

普通 CRUD:

BaseMapper

单个 Mapper 特殊查询:

Mapper + XML

很多 Mapper 共用同一种 SQL:

SQL Injector

记住:

SQL 注入器:

不是:

替代 XML。

而是:

扩展 BaseMapper。


总结

SQL 注入器并没有名字听起来那么神秘。

它的本质,其实就是:

把一套通用 SQL 方法,在项目启动时统一注册到所有 Mapper 中,让不同 Mapper 可以共享这些 SQL 能力。

所以它适合解决的是:

很多 Mapper

都有同一个 SQL

↓

重复代码

↓

统一抽象

↓

统一注册

↓

全部复用

最后,记住一句话就够了:

SQL 注入器不是用来写业务 SQL 的,而是用来扩展 MyBatis-Plus 通用 CRUD 能力的。

当一个 SQL 只有某一个 Mapper 会使用时,直接写 Mapper + XML 即可;当一个 SQL 希望所有 Mapper 都拥有时,SQL 注入器才是真正适合的解决方案。

MyBatis-Plus SQL 注入器是什么?一篇文章带你彻底搞懂!
http://clxhxhhr.top/posts/375/
作者
clxstart
发布于
2026-08-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。