zoukankan      html  css  js  c++  java
  • 【MybatisPlus进阶学习(八)】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();
          }
      

      结果如下:

      这里需要注意:

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

      2. 如果报以下错误

      当删除所有数据时,由于有的数据行有外键的约束,不允许你进行物理删除。使用语句删除外键即可,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);
          }
      

      结果如下:

    • 相关阅读:
  • 相关阅读:
    第五十四天:jQuery内容的基础:
    第五十三天dom基础
    第五十二天js的&#183;进阶
    第五十一天js的基础
    第四十九天css进阶
    第四十八天 html中的form和css基础
    第四十七天:web中德html初级:
    第42天IO模块
    第四十一天:协程操作
    第四十天线程的进阶
  • 原文地址:https://www.cnblogs.com/exmyth/p/15631495.html
Copyright © 2011-2022 走看看