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);
          }
      

      结果如下:

    • 相关阅读:
  • 相关阅读:
    高精度计算
    高精度除以低精度
    P1258 小车问题
    POJ 2352 stars (树状数组入门经典!!!)
    HDU 3635 Dragon Balls(超级经典的带权并查集!!!新手入门)
    HDU 3938 Portal (离线并查集,此题思路很强!!!,得到所谓的距离很巧妙)
    POJ 1703 Find them, Catch them(确定元素归属集合的并查集)
    HDU Virtual Friends(超级经典的带权并查集)
    HDU 3047 Zjnu Stadium(带权并查集,难想到)
    HDU 3038 How Many Answers Are Wrong(带权并查集,真的很难想到是个并查集!!!)
  • 原文地址:https://www.cnblogs.com/exmyth/p/15631495.html
Copyright © 2011-2022 走看看