当前位置: 首页 > news >正文

MyBatis-Plus——SQL注入器

MyBatis-Plus的SQL注入器其实是一种“扩展工具包”机制——当BaseMapper提供的默认方法(如selectById、deleteById)不够用时,我们可以通过它自定义通用方法,让所有Mapper接口都能直接使用。这里提供一个案例:自定义一个“删除表中所有数据”的deleteAll方法,用“工具箱”的比喻一步步拆解。

一、先理解核心需求:为什么需要自定义deleteAll?

MyBatis-Plus的BaseMapper虽然提供了很多基础方法,但没有“删除全表数据”的deleteAll方法(可能是为了安全,避免误操作)。如果多个表都需要“删除全表”功能,总不能在每个Mapper里重复写SQL吧?

这时候就需要SQL注入器:把deleteAll定义成“全局通用方法”,让所有继承BaseMapper的接口(比如StudentMapper、UserMapper)都能直接调用,不用重复开发。

二、逐步拆解:每个类的作用

1. 自定义方法类(DeleteAll):定义“具体工具”

// 注入方法类:相当于定义一个"删除全表"的工具
public class DeleteAll extends AbstractMethod {@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {// 1. 定义要执行的SQL:delete from 表名(表名通过tableInfo获取,自动适配不同表)String sql = "delete from " + tableInfo.getTableName();// 2. 定义方法名:和Mapper接口中声明的方法名一致(这里是deleteAll)String method = "deleteAll";// 3. 构建SqlSource:MyBatis中用于传递SQL的对象SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);// 4. 构建删除类型的MappedStatement(MyBatis执行SQL的核心对象)return this.addDeleteMappedStatement(mapperClass, method, sqlSource);}
}

作用:这是“具体工具的设计图”,定义了deleteAll方法要执行的SQL(删除全表)、方法名,以及如何生成MyBatis能识别的执行对象(MappedStatement)。

继承AbstractMethod的原因:MyBatis-Plus通过AbstractMethod统一管理方法生成逻辑,我们只需按照它的规范实现即可。

2. SQL注入器(MySqlInject):将“工具”放入“公共工具箱”

// SQL自动注入器:相当于把自定义工具放到所有Mapper都能访问的公共工具箱
@Component
public class MySqlInject extends AbstractSqlInjector {@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {List<AbstractMethod> methods = new ArrayList<>();// 把自定义的DeleteAll方法添加到方法列表中methods.add(new DeleteAll()); return methods;}
}

作用:注入器的职责是“收集所有自定义方法”,并在MyBatis-Plus启动时,将这些方法注入到所有继承BaseMapper的接口中。

简单说:没有注入器,DeleteAll方法只是一个孤立的类;有了注入器,它会告诉MyBatis-Plus:“把deleteAll方法加到所有Mapper里,让它们都能用”。

3. 在Mapper接口中声明方法:“告诉工具箱要用这个工具”

// StudentMapper:具体的工具箱,继承BaseMapper后,自动获得基础工具+注入的自定义工具
public interface StudentMapper extends BaseMapper<Student> {// 声明deleteAll方法(无需实现,因为注入器已经帮我们生成了实现)void deleteAll();
}

为什么只声明不实现?
因为DeleteAll类已经通过注入器生成了对应的SQL和执行逻辑,这里只是“告诉MyBatis:我要用这个方法”,实际执行时会找到注入器生成的实现。

4. 注销BlockAttackInnerInterceptor插件:“暂时关闭安全锁”

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));// 注释掉防全表删除插件:因为deleteAll就是全表删除,会被它拦截// interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;
}

原因:BlockAttackInnerInterceptor是MyBatis-Plus的“安全插件”,会拦截全表删除/更新(防止误操作)。而我们的deleteAll就是要全表删除,所以需要暂时注释掉,否则会执行失败。

5. 测试方法:“使用工具”

@Test
public void testDeleteAll() {// 直接调用StudentMapper中的deleteAll方法studentMapper.deleteAll();
}

此时调用的deleteAll,就是我们通过注入器自定义的全表删除方法。

三、完整执行流程:从启动到调用

用“工具箱准备→使用工具”的流程理解:

  1. 启动阶段:准备工具箱

    • 项目启动时,Spring会加载MySqlInject(因为加了@Component);
    • MySqlInject的getMethodList方法被调用,返回包含DeleteAll的方法列表;
    • MyBatis-Plus会根据这些方法,为所有继承BaseMapper的接口(如StudentMapper)生成对应的实现逻辑(即MappedStatement,包含SQL和执行方式);
    • 最终,StudentMapper不仅有BaseMapper的默认方法,还多了deleteAll方法。
  2. 调用阶段:使用工具

    • 执行studentMapper.deleteAll()时,MyBatis会找到注入器生成的MappedStatement;
    • 执行其中定义的SQL:delete from student(表名由TableInfo自动获取,对应Student实体类的表);
    • 数据库执行全表删除,完成操作。

四、总结

SQL注入器就像“全局工具注册中心”:

  • 自定义方法类(DeleteAll)是“工具的设计图”,定义了工具的功能(执行什么SQL);
  • 注入器(MySqlInject)是“工具管理员”,把工具分发到所有Mapper的“工具箱”里;
  • Mapper接口声明方法是“告诉管理员要用这个工具”;
  • 最终,我们可以在任何Mapper中直接使用这个工具(调用方法)。

这种机制的好处是:一次定义,到处使用,避免重复开发通用方法。

http://www.lryc.cn/news/618965.html

相关文章:

  • LintCode第1526-N叉树的前序遍历
  • RabbitMQ面试精讲 Day 20:RabbitMQ压测与性能评估
  • 【游戏优化笔记】开发中如何减少建筑和树木等环境元素的资源消耗?
  • 行业热点丨智能仿真时代:电子工程多物理场解决方案创新实践
  • 【盘古100Pro+开发板实验例程】FPGA学习 | 中值滤波 | 图像实验指导手册
  • Redis知识点+项目+面试八股
  • redis认识缓存击穿
  • Flutter UI Kits by Olayemi Garuba:免费开源的高质量UI组件库
  • Element用法---Loading 加载
  • React 腾讯面试手写题
  • Photoshop软件打开WebP文件格的操作教程
  • 第六十四章:AI的“觅食”之路:数据采集器设计与多源数据获取
  • Android性能优化:架构层面的性能考量
  • Android 引导式访问(屏幕固定 Screen Pinning)完整指南
  • CPPIO流
  • 北京JAVA基础面试30天打卡08
  • 信号反射规律
  • [激光原理与应用-254]:理论 - 几何光学 - 自动对焦的原理
  • W5500之“socket.c”中的相关函数
  • Vue接口平台小功能——发送报告到飞书
  • AWT与Swing深度对比:架构差异、迁移实战与性能优化
  • Unity数据可视化图表插件XCharts
  • Elasticsearch JS 自定义 ConnectionPool / Connection / Serializer、敏感信息脱敏与 v8 平滑迁移
  • python调研本地 DeepSeek API的例子
  • NLP—词向量转换评论学习项目分析真实案例
  • 【Vue 3 响应式系统深度解析:reactive vs ref 全面对比】
  • 【实时Linux实战系列】基于RFID的实时资产追踪系统
  • 当赞美来敲门:优雅接纳的艺术
  • 21.Linux HTTPS服务
  • GitHub的简单使用方法----(5)