• Mybatis-Plus如何自定义SQL注入器?


    有关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注入器全局配置

    @Component
    public 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
      */
    @Mapper
    public 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容器

    @Component
    public 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原稿和原图片。其它情况一律禁止转载!

  • 相关阅读:
    Fibonacci数列那些事!
    域渗透04-漏洞(CVE-2020-1472)
    04 后端增删改查【小白入门SpringBoot + Vue3】
    人工神经网络的分类包括,人工神经网络的分类有
    为什么在使用onnxruntime-gpu下却没有成功调用GPU?
    Html详解
    吴恩达老师机器学习课程笔记 02 单变量线性回归
    网络安全攻防对抗之隐藏通信隧道技术整理
    智慧公厕:城市公共厕所的未来之路
    tekton 和 Argocd的区别
  • 原文地址:https://www.cnblogs.com/qdhxhz/p/17246872.html