首页 > 数据库 >Mybatis-Plus如何自定义SQL注入器?

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

时间:2023-04-12 22:44:07浏览次数:56  
标签:自定义 Plus user SQL Mybatis public 注入

有关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<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> 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<T> extends BaseMapper<T> {
    
    /**
     * 全字段更新,不会忽略null值
     *
     * @param entity 实体对象
     */
    int alwaysUpdateSomeColumnById(T entity);

    /**
     * 全量插入,等价于insert
     * 
     * @param entityList 实体集合
     */
    int insertBatchSomeColumn(List<T> 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<UserDO> {

}

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<UserDO> userDOS = Lists.newArrayList(user, user1);
        mapper.insertBatchSomeColumn(userDOS);
    }
}

运行结果

alwaysUpdateSomeColumnById方法

insertBatchSomeColumn方法

成功!


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

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

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

在MyBaseMapper中添加findAll方法

public interface MyBaseMapper<T> extends BaseMapper<T> {
 
     /**
       *  查询所有用户
       */
      List<T> 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<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        /**
         * 自定义SQL注入器注入
         */
        methodList.add(new FindAll());
        return methodList;
    }
}

4、测试

 @Test
    public void findAll() {
         List<UserDO> userDOS = mapper.findAll();
    }

成功!

补充

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

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



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

标签:自定义,Plus,user,SQL,Mybatis,public,注入
From: https://www.cnblogs.com/qdhxhz/p/17246872.html

相关文章

  • Mysql四种事务隔离级别
    先了解一下事务的四大特性:ACID原子性(Atomicity)原子性就是不可拆分的特性,要么全部成功然后提交(commit),要么全部失败然后回滚(rollback)。MySQL通过RedoLog重做日志实现了原子性,在将执行SQL语句时,会先写入redologbuffer,再执行SQL语句,若SQL语句执行出错就会根据redologbuffer中的......
  • Mysql 入门之过滤数据(一)
    关键字:where、between、null知识点1、where关键字在Mysql中用于获取指定搜素条件的数据,这些条件也称之为过滤条件2、between为where子句的操作符,诸如=、<、>等符号功能类似3、关于null可以初步理解为它是Mysql中不确定的“值”,从根本上讲它都不是个“值”下面给出一些案......
  • cnetos8上RPM安装mysql8后,修改初始密码提示Your password does not satisfy the curre
    我在修改mysql8初始密码是遇到了Yourpassworddoesnotsatisfythecurrentpolicyrequirements,如果您的mysql版本5.x可能不太合适。下图是我遇到的问题: 意思是,密码不符合密码验证要求。但是mysql8的初始密码连验证要求都查不到,不过一般密码强度是不过我们可以密码设置为......
  • Android sqlite 数据库查询,插入,删除,更新demo<第1章>
    //20140424创建数据库帮助类DataBaseHelper,继承SQLiteOpenHelper, 1. 编写构造函数,实现数据库创建;publicstaticfinalStringTAG="ListViewActivity";privatestaticintVERSION=1;privatestaticfinalStringTABLE_NAME="user1";privatestaticfinalSt......
  • mysql性能优化二
    索引:高校检索数据的数据结构索引能干吗呢‘?索引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要。索引优化应该是对查询性能优化最有效的手段了。索引能够轻易将查询性能提......
  • centos安装MySQL8记录
    1.卸载mariadb因centos7默认安装了mariadb,会造成依赖冲突,按下列方式进行卸载:rpm-qa|grepmariadb#如果出现mariadb-libs-5.5.68-1.el7.x86_64#执行rpm-emariadb-libs--nodeps2.下载  注意权限:(chmod-R777/var/lib/mysql)(chmod-R777/var......
  • percona公司的proxysql安装与配置
    #####################    安装包类型:源码包rpm安装包免编译二进制                 ########################......
  • flask使用sqlalchemy
    flask使用sqlalchemyflask-sqlalchemy集成方案借助第三方模块flask-sqlalchemy,可以将sqlalchemy快速的集成到flask项目中。pipinstallflask_sqlalchemyfromflask_sqlalchemyimportSQLAlchemydb=SQLAlchemy()#产生一个SQLAlchemy对象#将db注册到app中db.init......
  • PostgreSQL 备忘清单_开发速查表分享
    PostgreSQL备忘清单PostgreSQL是一种特性非常齐全的自由软件的对象-关系型数据库管理系统(ORDBMS),是以加州大学计算机系开发的POSTGRES,4.2版本为基础的对象关系型数据库管理系统。POSTGRES的许多领先概念只是在比较迟的时候才出现在商业网站数据库中。PostgreSQL支持大部分的SQL标......
  • mysql查询过程优化--理论及实践过程总结
    首先推荐一篇写的特别详细的帖子,感觉写的太好了。全看懂了,就不用看我下面的废话了。https://blog.52ipc.top/archives/149.html然后记录点自己解决的经验正式开始写一下我的优化过程:问题:MySQL查询count()from(括号里有七八个leftjoin),导致查询速度特别慢,结果大概是40s+1、......