当前位置: 首页 > news >正文

mybatis-plus的批量新增insertBatchSomeColumn

MyBatis-Plus 是基于 MyBatis 进行封装的一套优秀的持久层框架,它提供了丰富的便捷操作方法和强大的代码生成器,大大简化了 MyBatis 的使用。在 MyBatis-Plus 中,我们可以使用 insertBatchSomeColumn 方法来实现批量新增指定字段的操作。

mybatis-plus的 IService接口 默认提供 saveBatch批量插入,也是唯一一个默认批量插入,在数据量不是很大的情况下可以直接使用,但这种是一条一条执行的效率上会有一定的瓶颈,在这里先看下saveBatch的执行情况

 

 

 

可以看到sql语句是一条一条执行的,插入多少条数据就相当于执行了多少次的插入sql, 点进saveBatch方法,看看内部是怎么实现的

 

 注意看,方法有一个事务注解,说明插入整批数据会作为一个事务进行,

默认1000条一次,怪不得执行时每隔1000条会处于一个准备执行状态,等待几秒后才会往下执行(这里等待的时间就是1000个单条的insert语句执行的时间)

再往下点是一个saveBatch接口,参数分别是插入的对象集合、插入批次数量也就是默认的1000

这里也有一个事务的注解,这是因为saveBatch是一个重载方法,插入的时候也可以指定插入批次数量调用

继续往下进入executeBatch

 

 

这里就是真正执行的方法了,idxLimit会对比DEFAULT_BATCH_SIZE和集合长度两个数中的最小数,作为批量大小,也就是说当集合长度不够1000,那么执行的时候批量大小就是集合的长度,就执行一次。

for循环中的consumer:对应的类型是一个函数式接口,代表一个接受两个输入参数且不返回任何内容的操作符。意思是给定两个参数sqlSession、循环中当前element对象,执行一次传递过来的consumer匿名函数。也就是上边源码里的插入匿名函数。
 

当i == indLimit时:执行一次预插入,并重新计算idxLimit的值

if中idxLimit计算规则:当前idxLimit加batchSize(默认1000) 和 集合长度 取最小值,计算出来的结果肯定不会超过集合的长度,最后的批次时idxLimit等于集合的长度,将这个值作为下一次执行预插入的时间点。

sqlSession.flushStatements():当有处于事务中的时候,起到一种预插入的作用,执行了这行代码之后,要插入的数据会锁定数据库的一行记录,并把数据库默认返回的主键赋值给插入的对象,这样就可以把该对象的主键赋值给其他需要的对象中去了,这里不是事务提交啊。

最后方法执行完后@Transactional注解会默认提交事务,如果调用的方法上还有@Transactional注解,默认的事务传播类型是Propagation.REQUIRED,不会新开启事务,如果没有@Transactional注解才会新开起事务

下面我们使用真正的批量新增方法insertBatchSomeColumn,看看两者的区别

1. 什么是批量新增指定字段

批量新增指定字段是指在一次 SQL 语句中执行多条 INSERT 语句,但是只插入指定的字段。批量新增指定字段可以提高数据操作效率,减少数据库与应用程序之间的网络传输次数,减轻数据库服务器的压力,提高系统的并发性能。

2. MyBatis-Plus 批量新增指定字段的方法的使用

mybatis-plus提供了InsertBatchSomeColumn批量insert方法。通过SQL 自动注入器接口 ISqlInjector注入通用方法 SQL 语句 然后继承 BaseMapper 添加自定义方法,全局配置 sqlInjector 注入 MP 会自动将类所有方法注入到 mybatis 容器中。我们需要通过这种方式注入下。
 

/**
 * 自定义Sql注入
 *
 */

public class EasySqlInjector extends DefaultSqlInjector {
    
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        // 注意:此SQL注入器继承了DefaultSqlInjector(默认注入器),调用了DefaultSqlInjector的getMethodList方法,保留了mybatis-plus的自带方法
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
        return methodList;
    }

}

 自定义EasyBaseMapper

/**
 * @author 武天
 * @date 2023/3/22 18:19
 */
public interface EasyBaseMapper<T> extends BaseMapper<T> {
    /**
     * 批量插入 仅适用于mysql
     *
     * @param entityList 实体列表
     * @return 影响行数
     */
    Integer insertBatchSomeColumn(Collection<T> entityList);
}

 mapper继承的这里改为继承刚书写的自定义mapper

/**
 * 
 * 
 * @author wutian
 * @email ${email}
 * @date 2022-10-03 22:12:06
 */
@Mapper
public interface BreakDownCluesDao extends EasyBaseMapper<ExcelBreakdownClues> {

}

调用测试

 

可以看到明显的区别,sql只执行了一条,后面都是入参逗号相隔的形式,耗时也有所优化,这是插入数量不是很多的情况,如果是上万条或者上千万条数据,这种形式的优越性就体现出来了 

3. 批量新增指定字段的注意事项

在使用 MyBatis-Plus 进行批量新增指定字段时,需要注意以下几点:

  • 每次新增的数据量不要过大,建议每批次新增的数据量控制在 1000 条以内。
  • 要新增的指定字段不能为 null,需要手动设置默认值。
  • 如果要新增的指定字段在实体类中有对应的字段值,会被忽略。

相关文章:

  • Linux内核IO基础知识与概念
  • Java - 配置中心初体验
  • 面试--每日一经
  • 算法训练营第五十九天|LeetCode647、516
  • 音视频开发—MediaCodec 解码H264/H265码流视频
  • 【python进阶】序列切片还能这么用?切片的强大比你了解的多太多
  • 内网升级“高效安全”利器!统信软件发布私有化更新管理平台
  • 什么是Vue
  • [图像识别]关于cv2库无法安装的故障问题解决,全网最全解决方案!本人亲身测试,参考了stackoverflow、51CTO等博客文章总结而成
  • 菜鸟刷题Day5
  • 22 k8s常用命令
  • 接口的定义和实现
  • 蓝桥杯冲刺 - week1
  • windows微服务部署
  • 深入了解JVM:Java程序背后的核心原理
  • 【mysql】环境安装、服务启动、密码设置
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • Javascript基础之Array数组API
  • PAT A1050
  • Python_OOP
  • Redis 中的布隆过滤器
  • vagrant 添加本地 box 安装 laravel homestead
  • Wamp集成环境 添加PHP的新版本
  • 代理模式
  • 基于 Babel 的 npm 包最小化设置
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 深入浏览器事件循环的本质
  • 使用 @font-face
  • 使用SAX解析XML
  • 通信类
  • 我从编程教室毕业
  • 一道面试题引发的“血案”
  • 用Visual Studio开发以太坊智能合约
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​TypeScript都不会用,也敢说会前端?
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (2015)JS ES6 必知的十个 特性
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (ZT)出版业改革:该死的死,该生的生
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (分布式缓存)Redis哨兵
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .net core使用ef 6
  • .NET delegate 委托 、 Event 事件,接口回调
  • .Net面试题4
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • .NET序列化 serializable,反序列化
  • .Net中的设计模式——Factory Method模式
  • [BUAA软工]第一次博客作业---阅读《构建之法》
  • [c++] 什么是平凡类型,标准布局类型,POD类型,聚合体
  • [CareerCup] 13.1 Print Last K Lines 打印最后K行
  • [Java] 模拟Jdk 以及 CGLib 代理原理
  • [java]删除数组中的某一个元素