【Mybatis-Plus进阶学习(八)】SQL注入器
使用SQL注入器就可以自定义例如selectById的默认方法。
实现步骤
Step1:创建定义方法的类;
Step2:创建注入器;
Step3:在Mapper中加入自定义方法。自定义注入器的简单使用
第一步:创建定义方法的类
public class DeleteAllMethod extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
//执行的SQL
String sql = "delete from " + tableInfo.getTableName();
//mapper接口方法名
String method = "deleteAll";
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return addDeleteMappedStatement(mapperClass, method, sqlSource);
}
}
第二步:创建注入器
@Component
public class MySqlInjector extends DefaultSqlInjector { @Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
//MP自定义的SQL语句,如果不添加,MP自定义的语句就不能用了
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new DeleteAllMethod());
return methodList;
} }
DefaultSqlInjector、AbstractSqlInjector、ISqlInjector都能继承。
第三步:在UserMapper中加入自定义方法deleteAll
/**
* 删除所有数据
* @return 影响行数
*/
int deleteAll();
第四步:测试
@Test
public void deleteAll() {
userMapper.deleteAll();
}
结果如下:

这里需要注意:
不知道大家还记不记得之前逻辑删除,3.1.2之前的版本配置了一个SQL注入器。自定义SQL注入器不可以和逻辑删除一起配置,因为不能同时制定两个sql注入器,所以报错。有一个办法就是MySqlinjector不要继承DefaultSqlInjector直接继承LogicSqlInjector就可以了,这样配置这一个sql注入器,就既能使用逻辑删除又能加入自定义方法了。
如果报以下错误

当删除所有数据时,由于有的数据行有外键的约束,不允许你进行物理删除。使用语句删除外键即可,
alter table user drop foreign key manager_fk;。或者把外键字段原来默认的Restrict改成CASCADE。同时附上初始化数据语句,可以多次尝试
#初始化数据:
INSERT INTO user (id, name, age, email, manager_id
, create_time)
VALUES (1087982257332887553, '大boss', 40, 'boss@baomidou.com', NULL
, '2019-01-11 14:20:20'),
(1088248166370832385, '王天风', 25, 'wtf@baomidou.com', 1087982257332887553
, '2019-02-05 11:12:22'),
(1088250446457389058, '李艺伟', 28, 'lyw@baomidou.com', 1088248166370832385
, '2019-02-14 08:31:16'),
(1094590409767661570, '张雨琪', 31, 'zjq@baomidou.com', 1088248166370832385
, '2019-01-14 09:15:15'),
(1094592041087729666, '刘红雨', 32, 'lhm@baomidou.com', 1088248166370832385
, '2019-01-14 09:48:16');
优化
如果每张表都需要删除全部,那我们为每个Mapper都写一个deleteAll()方法,非常的繁琐。这时候我们可以自己建立一个MyMapper接口,MyMapper接口继承BaseMapper,而类似于UserMapper的自定义Mapper全部继承MyMapper,这样我们就只需要在MyMapper中编写一个deleteAll方法,再由UserMpper和其他Mapper继承就可以实现deleteAll()方法的重用。
选装件InsertBatchSomeColumn
选择件其实也是自定义SQL注入器,但是是由官方提供的。InsertBatchSomeColumn的主要功能是批量新增数据,自选字段insert。接下来让我们看看是如何实现的吧。
第一步:注入器中加入方法@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
//MP自定义的SQL语句,如果不添加,MP自定义的语句就不能用了
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new DeleteAllMethod());
//加入选装件InsertBatchSomeColumn,同时排除逻辑删除字段
methodList.add(new InsertBatchSomeColumn(t->!t.isLogicDelete()));
return methodList;
}
第二步:在MyMapper中加入insertBatchSomeColumn方法
public interface MyMapper<T> extends BaseMapper<T> {
/**
* 删除所有数据
* @return 影响行数
*/
int deleteAll(); int insertBatchSomeColumn(List<T> list);
}
第三步:测试
@Test
public void insertBatchSomeColumn() { User user = new User();
user.setName("王聚义");
user.setAge(26);
user.setEmail("wjy@163.com");
user.setManagerId(1088248166370832385L); User user2 = new User();
user2.setName("王收义");
user2.setAge(28);
user2.setEmail("wsy@163.com");
user2.setManagerId(1088248166370832385L); List<User> list = new ArrayList<>();
list.add(user);
list.add(user2); userMapper.insertBatchSomeColumn(list);
}

可以看出批量插入成功。
需要注意的是,User对象中为Null的值会覆盖没有被排除字段的默认值。例如version的默认值为1,但是我们插入的User的version为null,如果version这个字段在注入器组件中没有被排除,结果数据库中的值应该为null。
同时作者在注解中也提示,选装器只在mysql中测试过,所以慎用。
选装件LogicDeleteByIdWithFill
LogicDeleteByIdWithFill的主要功能是根据id逻辑删除数据并带字段填充功能。例如在删除的时候需要添加操作人。
第一步:注入器中加入方法
methodList.add(new LogicDeleteByIdWithFill());
第二步:在MyMapper中加入方法
int deleteByIdWithFill(T entity);
第三步:测试
@Test
public void deleteByIdWithFill() {
User user = new User();
user.setId(1346432120618147841L);
user.setUpdateTime(LocalDateTime.now());
userMapper.deleteByIdWithFill(user);
}
注意,如果想在删除的同时修改数据,被修改的数据必须有自动填充标识,不然无法完成更新。结果如下:

选装件AlwaysUpdateSomeColumnById
AlwaysUpdateSomeColumnById的主要功能是根据id更新固定的某些字段。
第一步:注入器中加入方法
methodList.add(new AlwaysUpdateSomeColumnById(t->!t.getColumn().equals("name")));
第二步:在MyMapper中加入方法
int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY) T entity);
第三步:测试
@Test
public void alwaysUpdateSomeColumnById() {
User user = new User();
user.setId(1346432120618147841L);
user.setName("王地风");
user.setAge(16);
userMapper.alwaysUpdateSomeColumnById(user);
}
结果如下:

- 相关阅读:
【Mybatis-Plus进阶学习(八)】SQL注入器的更多相关文章
- Mybatis基础进阶学习2
Mybatis基础进阶学习2 1.测试基本结构 2.三个POJO package com.pojo; import java.io.Serializable; import java.util.Dat ...
- Java数据持久层框架 MyBatis之API学习八(Java API详解)
对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...
- 【译】SQL Server索引进阶第八篇:唯一索引
原文:[译]SQL Server索引进阶第八篇:唯一索引 索引设计是数据库设计中比较重要的一个环节,对数据库的性能其中至关重要的作用,但是索引的设计却又不是那么容易的事情,性能也不是那么轻易就 ...
- (转)MyBatis框架的学习(四)——Mapper.xml文件中的输入和输出映射以及动态sql
http://blog.csdn.net/yerenyuan_pku/article/details/71893689 前面对MyBatis框架的学习中,我们对Mapper.xml映射文件多少有些了解 ...
- mybatis源码学习:基于动态代理实现查询全过程
前文传送门: mybatis源码学习:从SqlSessionFactory到代理对象的生成 mybatis源码学习:一级缓存和二级缓存分析 下面这条语句,将会调用代理对象的方法,并执行查询过程,我们一 ...
- mybatis源码学习--spring+mybatis注解方式为什么mybatis的dao接口不需要实现类
相信大家在刚开始学习mybatis注解方式,或者spring+mybatis注解方式的时候,一定会有一个疑问,为什么mybatis的dao接口只需要一个接口,不需要实现类,就可以正常使用,笔者最开始的 ...
- Java数据持久层框架 MyBatis之API学习一(简介)
对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...
- Mybatis 源码学习系列
前言 很久以前,我们学习了Java,从一个控制台的 Hello world .开始,我们进入了面向对象的世界. 然后由学习了SQL语言,可以写出SQL语句来将尘封在硬盘之下的数据库数据,展现出来. 后 ...
- MyBatis基础入门《八》查询参数传入Map
MyBatis基础入门<八>查询参数传入Map 描述: 在执行select查询数据的时候,方法传入的参数是java.util.Map类型. 接口方法: xml文件 注意: 书写SQL语句的 ...
- SVG 学习<八> SVG的路径——path(2)贝塞尔曲线命令、光滑贝塞尔曲线命令
目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...
随机推荐
- Pytorch 基于加权平滑过渡的无缝拼接
基于加权平滑过渡的无缝拼接 背景 在做照片数字人视频生成的时候,为了达到快速响应实时播放的需求,即视频的生成速度 必须小于 音频的播放速度. 因此,我们截取了一部分较小的可动区域进行推理生成,然后把生 ...
- 墨天轮沙龙 | 亚马逊云科技李君:见微知著 - Serverless云原生数据库概览
导读 以业务为导向的数据库需要满足现代化应用的需要,以 Serverless 数据库为代表,云数据库正在迅速发展成熟,并带来更好的可访问性和高可用性,还有高扩展性与可迁移性. [墨天轮数据库沙龙-Se ...
- 61.null和undefined的区别
null 是空指针,用来保存准备使用的对象,但是现在还没有,用来占位 : undefined 是未定义,是声明了变量但是没有初始化 :
- webpack中 loader和plugin的区别
首先 ,loader 是文件加载器,能够加载资源文件,并对文件进行一些处理,如翻译,压缩 ,最终一起打包到指定的文件中 :loader 运行在打包项目之前 : plugin 是插件 ,plugin赋予 ...
- 05 Transformer 中的前馈神经网络(FFN)的实现
2:20:理论链接 博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链 ...
- Docker挂载jar包运行脚本
下载镜像 docker pull openjdk:8 执行命令 docker run -d -p 9001:8081 -v /opt/springboot-docker-1.0.jar:/var/li ...
- Kubernetes 对接 GlusterFS 磁盘扩容实战
前言 知识点 定级:入门级 使用 Heketi Topology 扩容磁盘 使用 Heketi CLI 扩容磁盘 实战服务器配置 (架构 1:1 复刻小规模生产环境,配置略有不同) 主机名 IP CP ...
- Chirpy+Github
相关网址 Chirpy 示例:网页上有官方教程,我写的肯定不全 Chirpy 示例仓库:这个就是包含官方教程的那个示例的仓库 Chirpy 模板仓库:直接 fork 这个仓库,快速搭建,没有多余的东西 ...
- 【斩虫】Hadoop中作业执行刚开始就挂掉的两种情况
开门见山. 最近在搭建基于 Hadoop 3.3.6 的高可用集群时,遇到了虽然守护进程能正常启动,但是提交 WordCount 示例程序后作业没有办法启动执行的情况(刚开始就挂了),查看日志发现主要 ...
- 【填算符】(log 值域的做法)
比赛在这里呢 填算符 下发题解说的神马东西,赛时根本想不到 讲一个赛时想得到的 \(O(n\log 值域)\) 的思路,很好理解 我们处理出二进制下每一位上的 1 的最后一次出现的位置,将第 \(i\ ...