logo

当前位置:首页>热门 > >正文

环球微头条丨Mybatis-Plus如何自定义SQL注入器?

环球微头条丨Mybatis-Plus如何自定义SQL注入器?
2023-04-13 04:52:35 来源:博客园

有关Mybatis-Plus常用功能之前有做过一篇总结:


【资料图】

MyBatisPlus常用功能总结!(附项目示例)

一、什么是SQL注入器

我们在使用Mybatis-Plus时,dao层都会去继承BaseMapper接口,这样就可以用BaseMapper接口所有的方法,

BaseMapper中每一个方法其实就是一个SQL注入器

在Mybatis-Plus的核心(core)包下,提供的默认可注入方法有这些:

那如果我们想自定义SQL注入器呢,我们该如何去做?

比如在Mybatis-Plus中调用updateById方法进行数据更新默认情况下是不能更新空值字段的。

而在实际开发过程中,往往会遇到需要将字段值更新为空值的情况。

那如何让Mybatis-Plus支持空值更新呢?

如果仅是想实现支持更新空值字段并不需要我们自定义SQL注入器,因为Mybatis-Plus提供了几个扩展SQL注入器。

二、内置扩展SQL注入器有哪些?1、自带扩展SQL注入器

Mybatis-Plus 扩展SQL注入器在扩展包下,为我们提供了可扩展的可注入方法:

AlwaysUpdateSomeColumnById: 根据id更新字段(全量更新不忽略null字段),updateById默认会自动忽略实体中null值字段。

InsertBatchSomeColumn: 真实批量插入,saveBatch其实是伪批量插入。

LogicDeleteBatchByIds: 逻辑删除增加填充功能,比如删除的时候填充更新时间、更新人。

Upsert: 插入一条数据(选择字段插入)。

2、SQL注入器全局配置
@Componentpublic class MySqlInjector extends DefaultSqlInjector {        @Override    public List getMethodList(Class mapperClass, TableInfo tableInfo) {        List methodList = super.getMethodList(mapperClass, tableInfo);        /**         * 把两个扩展内置扩展SQL注入器注入         */        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));        methodList.add(new AlwaysUpdateSomeColumnById(i -> i.getFieldFill() != FieldFill.INSERT));        return methodList;    }}
3、自定义Mapper
public interface MyBaseMapper extends BaseMapper {        /**     * 全字段更新,不会忽略null值     *     * @param entity 实体对象     */    int alwaysUpdateSomeColumnById(T entity);    /**     * 全量插入,等价于insert     *      * @param entityList 实体集合     */    int insertBatchSomeColumn(List entityList);}
三、扩展SQL注入器示例测试1、用户表
CREATE TABLE `user` (  `id` int unsigned  AUTO_INCREMENT COMMENT "主键",  `username` varchar(128)  COMMENT "用户名",  `phone` varchar(32)  COMMENT "手机号",  `sex` char(1)  COMMENT "性别",  `create_time` datetime  COMMENT "创建时间",  `update_time` datetime  COMMENT "更新时间",  `deleted` tinyint DEFAULT "0" COMMENT "1、删除 0、未删除",  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 
2、创建对应实体
@Data@Accessors(chain = true)@TableName("user")public class UserDO implements Serializable {    private static final long serialVersionUID = 1L;    @TableId(value = "id", type = IdType.AUTO)    private Integer id;    /**     * 用户名     */    @TableField("username")    private String username;    /**     * 手机号     */    @TableField("phone")    private String phone;    /**     * 性别     */    @TableField("sex")    private String sex;    /**     * 创建时间     */    @TableField(value = "create_time",fill = FieldFill.INSERT)    private LocalDateTime createTime;    /**     * 更新时间     */    @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)    private LocalDateTime updateTime;    /**     * 1、删除 0、未删除     */    @TableField(value = "deleted",fill = FieldFill.INSERT)    private Integer deleted;}

其它有关代码这里就不粘贴了,具体看项目源码。

我们自定义的Mapper不再继承BaseMapper而是继承MyBaseMapper

/**  *  通用mapper接口,以后创建其他mapper接口时,不再继承BaseMapper,而是继承MyBaseMapper  */@Mapperpublic interface UserMapper extends MyBaseMapper {}
3、测试代码
@SpringBootTest@RunWith(SpringRunner.class)@ComponentScan("com.jincou.mybatisplus.dao")public class SqlInjectorTest  {   @Autowired   private UserMapper mapper;       @Test    public void alwaysUpdateSomeColumnById() {        UserDO user = new UserDO();        user.setUsername("小小");        user.setPhone(null);        user.setSex("女");        user.setId(1);        mapper.alwaysUpdateSomeColumnById(user);    }        @Test    public void insertBatchSomeColumn() {        UserDO user = new UserDO();        user.setUsername("zhangsan");        user.setPhone("13811111111");        user.setSex("女");        UserDO user1 = new UserDO();        user1.setUsername("lisi");        user1.setPhone("13822222222");        user1.setSex("男");        ArrayList userDOS = Lists.newArrayList(user, user1);        mapper.insertBatchSomeColumn(userDOS);    }}

运行结果

alwaysUpdateSomeColumnById方法

insertBatchSomeColumn方法

成功!

四、如何自定义SQL注入器?

在实际开发过程中,当Mybatis-Plus自带的一些SQL注入器不满足我们的条件时,我们就需要自定义SQL注入器,整个流程也非常简单

这里我们以一个很简单的findAll方法为例进行学习。

在MyBaseMapper中添加findAll方法
public interface MyBaseMapper extends BaseMapper {      /**       *  查询所有用户       */      List findAll();}
2、编写FindAll SQL注入器
public class FindAll extends AbstractMethod {    public FindAll() {        super("findAll");    }    public FindAll(String methodName) {        super(methodName);    }    @Override    public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) {        /* 执行 SQL ,动态 SQL 参考类 SqlMethod */        String sql = "select *  from " + tableInfo.getTableName();        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);        return this.addSelectMappedStatementForTable(mapperClass, sqlSource, tableInfo);    }}
3、注册到Spring容器
@Componentpublic class MySqlInjector extends DefaultSqlInjector {    @Override    public List getMethodList(Class mapperClass, TableInfo tableInfo) {        List methodList = super.getMethodList(mapperClass, tableInfo);        /**         * 自定义SQL注入器注入         */        methodList.add(new FindAll());        return methodList;    }}
4、测试
@Test    public void findAll() {         List userDOS = mapper.findAll();    }

成功!

补充

项目地址: https://github.com/yudiandemingzi/spring-boot-study

Mybatis-Plus官方SQL注入器示例地址:https://baomidou.com/pages/42ea4a/

声明: 公众号如需转载该篇文章,发表文章的头部一定要 告知是转至公众号: 后端元宇宙。同时也可以问本人要markdown原稿和原图片。其它情况一律禁止转载!

标签: