广告
返回顶部
首页 > 资讯 > 数据库 >Mybatis-Plus的SQL注入器实现批量插入/修改,效率比较
  • 781
分享到

Mybatis-Plus的SQL注入器实现批量插入/修改,效率比较

mybatissqlmysql 2023-08-19 22:08:37 781人浏览 泡泡鱼
摘要

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

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

在这里插入图片描述

插入10000条数据

  1. mybatis-plus的saveBatch耗时3.6s
##sql格式(不止这些字段) <script> <foreach collection="list" item="item" separator=";"> insert into user (name, age) values ("张三",17) </foreach> </script>
  1. insert values 耗时1.8s
##sql格式(不止这些字段)insert into user (name, age) values ("张三", 17), ("李四", 18);

更新10000条数据

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

综合比较效率

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

自定义sql注入器

在这里插入图片描述

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 {        @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中写的各种标签