相关推荐recommended
Mybatis-Plus的SQL注入器实现批量插入修改,效率比较
作者:mmseoamin日期:2023-12-11

Sql效率

mysql支持一条sql语句插入多条数据。但是Mybatis-Plus中默认提供的saveBatch、updateBatchById方法并不能算是真正的批量语句,而是遍历实体集合执行INSERT_ONE、UPDATE_BY_ID语句。

mybatis-plus虽然做了分批请求、一次提交的处理。但如果jdbc不启用配置rewriteBatchedStatements,那么批量提交的sql到了mysql就还是一条一条执行,mysql并不会将这些sql重写为insert多值插入,相比一条sql批量插入,性能上会差点。

rewriteBatchedStatements文档

https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-performance-extensions.html#cj-conn-prop_rewriteBatchedStatements

Mybatis-Plus的SQL注入器实现批量插入修改,效率比较,在这里插入图片描述,第1张

插入10000条数据

  1. mybatis-plus的saveBatch耗时3.6s
##sql格式(不止这些字段)
 
  1. insert values 耗时1.8s
##sql格式(不止这些字段)
insert into user (name, age) values ("张三", 17), ("李四", 18);

更新10000条数据

  1. mybatis-plus的updateBatchById 耗时3.1s
##sql格式(不止这些字段)
 
  1. update case when
  • 使用Update case when 是可以一条sql批量更新,一次提交10000条会卡死,得分批处理
  • 最终耗时更久,需要5.8s。
    ##sql格式(不止这些字段)
    update
            user
    set
            name=
            (
            case id when 1 then '张三'
            when 2 then '李四'
            else name
    end),
            age=
            (
            case id when 1 then 16
            when 2 then 26
            else age
    end)
    where
            id in ( 1 , 2 )
    

    综合比较效率

    10000条数据mybatis-plus自定义sql
    批量插入3.6s1.8s
    批量更新3.1s5.8s

    自定义sql注入器

    Mybatis-Plus的SQL注入器实现批量插入修改,效率比较,在这里插入图片描述,第2张

    1.mybatis-plus给我们提供了自定义sql注入的功能,我们可以自己定义类似insert()、updateById()的方法。

    2.首先mybatis-plus在com.baomidou.mybatisplus.extension,给我们提供了4个自带的注入方法。

    1. AlwaysUpdateSomeColumnById 根据Id更新每一个字段,不忽略null字段,数据为null则更新为null。
    2. InsertBatchSomeColumn 单条sql批量插入,通过单SQL的insert语句实现批量插入。
    3. LogicDeleteByIdWithFill 带自动填充的逻辑删除,比如自动填充更新时间、操作人。
    4. Upsert 更新or插入,根据唯一约束判断是执行更新还是删除,相当于提供insert on duplicate key update支持,但mysql应该没有此语法。

    3. 类似com.baomidou.mybatisplus.core.enums.SqlMethod里的模板,我们可以继承com.baomidou.mybatisplus.core.injector.AbstractMethod方法来自行定义批量插入/修改的模板方法

    import com.baomidou.mybatisplus.core.injector.AbstractMethod;
    import com.baomidou.mybatisplus.core.metadata.TableInfo;
    import org.apache.ibatis.executor.keygen.NoKeyGenerator;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.mapping.SqlSource;
    public class InsertBatchMethod extends AbstractMethod {
        /**
         * insert into user(id, name, age) values (2, "b", 24), (3, "c", 26);
         
         */
        @Override
        public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) {
            final String sql = "";
            final String fieldSql = prepareFieldSql(tableInfo);
            final String valueSql = prepareValuesSql(tableInfo);
            final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);
            SqlSource sqlSource = languageDriver.createSqlSource(
            configuration, sqlResult, modelClass);
            
            //加入Configuration中的Map mappedStatements,
            //这个mappedStatements保存我们xml中写的各种标签