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

  • 相关阅读:
    HTML小游戏9 —— 潜行游戏《侠盗罗宾汉》(附完整源码)
    rocketmq-spring-boot-starter 2.1.0 事务消息移除参数txProducerGroup
    springAOP面试题
    DHT11 温湿度传感器
    【AGC】调测应用内消息服务的收不到弹窗的问题
    基于云原生存储的容器持久化存储方案
    Spark 广播变量和累加器
    项目干系人管理的10个关键原则
    从数据的属性看数据资产
    YOLO物体检测-系列教程2:YOLOV2整体解读
  • 原文地址:https://www.cnblogs.com/qdhxhz/p/17246872.html