Mybatis中批量插入foreach优化
数据库批量入库方常见方式:Java中foreach和xml中使用foreach
两者的区别:
通过Java的foreach循环批量插入:
当我们在Java通过foreach循环插入的时候,是一条一条sql执行然后将事物统一交给spring的事物来管理(@Transactional),当遇到错误时候可以全部回滚。
缺点:每次执行都会消耗网络io以及磁盘io,执行效率很低。
通过xml中使用foreach批量插入:
在xml中使用foreach会遍历生成一个sql语句然后一次发送到数据库,只需要一次网络 io
如下所示:
<foreach collection="list" item="item" separator=";">insert into user(id, name, phone)values (#{id}, #{name}, #{phone})</foreach>
缺点:如果数据量过大则会生成一个很大的sql,会导致io异常
上诉xml还有优化的写法,如下:
insert into user(id, name, phone)values<foreach collection="list" item="item" separator=",">(#{id}, #{name}, #{phone})</foreach>
两者的区别是在遍历的内容,第一种写法会生成多条单独的插入sql语句(insert into ,,,,,; insert into ....;),第二种是只遍历values后面的内容,使用了insert into .... values 的语法,减少了sql的大小。
除了以上的两种方法之外还可以自己手动实现一个批量插入或修改的工具类(挺好用的)
如下所示:
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;import java.util.List;
import java.util.function.BiFunction;/*** @author light pwd* @description* @date 2024/10/25*/
@Component
public class MyBatchUtils {private static final Logger LOG = LoggerFactory.getLogger(MyBatchUtils.class);/*** 每次处理1000条*/private static final int BATCH_SIZE = 1000;@Autowiredprivate SqlSessionFactory sqlSessionFactory;/*** 批量处理修改或者插入* 变成一条一条的数据,然后最后一起执行。并不是 insertBatch那种方式* @param data 需要被处理的数据* @param mapperClass Mybatis的Mapper类* @param function 自定义处理逻辑* @return int 影响的总行数*/public <T, U, R> int batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T, U, R> function) {int i = 1;SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);try {U mapper = batchSqlSession.getMapper(mapperClass);int size = data.size();for (T element : data) {function.apply(element, mapper);if (i % BATCH_SIZE == 0 || i == size) {batchSqlSession.flushStatements();}i++;}// 非事务环境下强制commit,事务情况下该commit相当于无效(交给spring的事物来管理)batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());} catch (Exception e) {batchSqlSession.rollback();LOG.error(e.getMessage());throw BusinessException.of(CommonErrorCodes.RUN_TIME_EXCEPTION, "MybatisBatchUtilsException");} finally {batchSqlSession.close();}return i - 1;}
}
该方法既结合了Java种foreach的优势,又结合了在xml种foreach的优势。这种方式与mybatis-plus的insertBatch是不同的,mybatis-plus默认提供的insertBatch方法本质是一条一条sql执行然后一起提交。
该方法对于大数据量会自动分批插入,每次1000条的插入到数据库,省去了分批处理。
用法也很简单:
batchUtils.batchUpdateOrInsert(haveIdColumn, PreColumnConfigMapper.class,(item, mapper) -> mapper.updateOne(item, createTime, createrId));batchUtils.batchUpdateOrInsert(noIdLine, PreLineConfigMapper.class,(item, mapper) -> mapper.insertOne(item, createTime, createrId));
其中batchUtils就是通过spring注入进来的MyBatchUtils的bean,haveIdColumn/noIdLine是一个待插入的List数据,PreLineConfigMapper/PreColumnConfigMapper都是mapper文件,
他们得updateOne和insertOne xml方法如下所示(我是pg数据库,mysql是类似的):
<update id="updateOne" parameterType="com.jiuaoedu.serviceeducation.pre.pojo.PreColumnConfig">update service_education.pre_column_configset type = #{bean.type,jdbcType=VARCHAR}, grade = #{bean.grade,jdbcType=VARCHAR}, subject = #{bean.subject,jdbcType=VARCHAR},name = #{bean.name,jdbcType=VARCHAR}, name_id = #{bean.nameId,jdbcType=VARCHAR},order_num = #{bean.orderNum,jdbcType=INTEGER},creater_id = #{createrId,jdbcType=BIGINT},create_time = #{createTime,jdbcType=TIMESTAMP}, target_num = null, class_num = null, del = 1where column_id = #{bean.columnId,jdbcType=BIGINT}</update>
<insert id="insertOne" parameterType="com.jiuaoedu.serviceeducation.pre.pojo.PreLineConfig">insert into service_education.pre_line_config(plan_id, group_id, title,type, start_date, end_date, start_time, end_time, week, order_num,count_date,year,term, time_order, create_time, creater_id)values(#{bean.planId,jdbcType=BIGINT},#{bean.groupId,jdbcType=VARCHAR}, #{bean.title,jdbcType=VARCHAR},#{bean.type,jdbcType=VARCHAR},#{bean.startDate,jdbcType=TIMESTAMP}, #{bean.endDate,jdbcType=TIMESTAMP},#{bean.startTime,jdbcType=TIME},#{bean.endTime,jdbcType=TIME},#{bean.week,jdbcType=VARCHAR},#{bean.orderNum,jdbcType=INTEGER}, #{bean.countDate,jdbcType=TIMESTAMP},#{bean.year,jdbcType=INTEGER},#{bean.term,jdbcType=VARCHAR}, #{bean.timeOrder,jdbcType=INTEGER},#{createTime,jdbcType=TIMESTAMP}, #{createrId,jdbcType=BIGINT})</insert>
注意事项:当在有事物的方法A中使用MyBatchUtils 工具类的时候,工具类的事物是跟方法A同步的,即方法A回滚则执行的所有数据都会回滚
当在没有事物的方法A中使用时:因为MyBatchUtils 会分批次插入所以每批次会有一个事物,提交也是一个批次一起提交,回滚也只回滚一个批次
奋斗不止,进步无止境,让人生在追求中焕发光彩!!!
相关文章:
Mybatis中批量插入foreach优化
数据库批量入库方常见方式:Java中foreach和xml中使用foreach 两者的区别: 通过Java的foreach循环批量插入: 当我们在Java通过foreach循环插入的时候,是一条一条sql执行然后将事物统一交给spring的事物来管理(Transa…...

Word VBA如何间隔选中多个(非连续)段落
实例需求:Word文档中的有多个段落,段落总数量不确定,现在需要先选中所有基数段落,即:段落1,段落3 … ,然后一次性设置粗体格式。 也许有的读者会认为这个无厘头的需求,循环遍历遍历文…...
Linux系统常用操作与命令指南
一、快捷分类 1、移动光标 h, j, k, l 左, 下, 上, 右 Ctrl-F:下翻一页 Ctrl-B:上翻一页 Ctrl-U:上翻半页 Ctrl-d:下翻半页 0:跳至行首,不管有无缩进,就是跳到第0个字…...

StructuredStreaming (一)
一、sparkStreaming的不足 1.基于微批,延迟高不能做到真正的实时 2.DStream基于RDD,不直接支持SQL 3.流批处理的API应用层不统一,(流用的DStream-底层是RDD,批用的DF/DS/RDD) 4.不支持EventTime事件时间(一般流处理都会有两个时间:事件发生的事件&am…...

由播客转向个人定制的音频频道(1)平台搭建
项目的背景 最近开始听喜马拉雅播客的内容,但是发现许多不方便的地方。 休息的时候收听喜马拉雅,但是还需要不断地选择喜马拉雅的内容,比较麻烦,而且黑灯操作反而伤眼睛。 喜马拉雅为代表的播客平台都是VOD 形式的࿰…...
[自然语言处理] [AI]深入理解语言与情感分类:从基础到深度学习的进展
语言是人类智能的核心组成部分,具有极高的复杂性和多样性。理解语言,尤其是语言中的隐含部分,向来是人工智能研究的一个巨大挑战。图灵测试本身便是一场关于语言生成与理解的比赛,旨在检验机器是否能够模拟人类的语言能力。随着深度学习的飞速发展,语音识别、情感分析等自…...

【GPTs】Gif-PT:DALL·E制作创意动图与精灵动画
博客主页: [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 💯GPTs指令💯前言💯Gif-PT主要功能适用场景优点缺点 💯小结 💯GPTs指令 中文翻译: 使用Dalle生成用户请求的精灵图动画&#…...
云原生周刊:Istio 1.24.0 正式发布
云原生周刊:Istio 1.24.0 正式发布 开源项目推荐 Kopf Kopf 是一个简洁高效的 Python 框架,只需几行代码即可编写 Kubernetes Operator。Kubernetes(K8s)作为强大的容器编排系统,虽自带命令行工具(kubec…...

Linux设置jar包开机启动
操作系统环境:CentOS 7 【需要 root 权限,使用 root 用户进行操作 或 普通用户使用 sudo 进行操作】 一、系统服务的方式 原理:利用系统服务管理应用程序的生命周期, systemctl 为系统服务管理工具 systemctl start applicati…...

计算机视觉和机器人技术中的下一个标记预测与视频扩散相结合
一种新方法可以训练神经网络对损坏的数据进行分类,同时预测下一步操作。 它可以为机器人制定灵活的计划,生成高质量的视频,并帮助人工智能代理导航数字环境。 Diffusion Forcing 方法可以对嘈杂的数据进行分类,并可靠地预测任务的…...
C语言之简单的获取命令行参数和环境变量
C语言之简单的获取命令行参数和环境变量 本人的开发环境为WIN10操作系统用VMWARE虚拟的UBUNTU LINUX 18.04LTS!!! 所有代码的编辑、编译、运行都在虚拟机上操作,初学的朋友要注意这一点!!! 详细…...

STL之vecor的使用(超详解)
目录 1. C/C中的数组 1.1. C语言中的数组 1.2. C中的数组 2. vector的接口 2.1. vector的迭代器 2.2. vector的初始化与销毁 2.3. vector的容量操作 2.4. vector的访问操作 2.5. vector的修改操作 💓 博客主页:C-SDN花园GGbond ⏩ 文章专栏…...

SystemVerilog学习笔记(一):数据类型
在systemverilog中,主要包含以下数据类型: 4值类型2值类型数组字符串结构体和联合体枚举自定义类型 无符号数:无符号数的符号不使用任何标志,即无符号数只能存储正数。无符号二进制数的范围从 0 到 ((2^n) - 1),n 表…...

Linux软件包管理与Vim编辑器使用指南
目录 一、Linux软件包管理器yum 1.什么是软件包? 2.什么是软件包管理器? 3.查看软件包 4.安装软件 编辑 5.卸载软件 Linux开发工具: 二、Linux编辑器---vim 1.vim的基本概念 (1) 正常/普通模式(Normal mode࿰…...
每日一练 | 包过滤防火墙的工作原理
01 真题题目 包过滤防火墙对哪一层的数据报文进行检查? A. 应用层 B. 物理层 C. 网络层 D. 链路层 02 真题答案 C 03 答案解析 包过滤防火墙是一种基本的安全设备,它通过检查进出网络的数据包来决定是否允许该数据包通过。 这种类型的防火墙主要关注…...

AR眼镜方案_AR智能眼镜阵列/衍射光波导显示方案
在当今AR智能眼镜的发展中,显示和光学组件成为了技术攻坚的主要领域。由于这些组件的高制造难度和成本,其光学显示模块在整个设备的成本中约占40%。 采用光波导技术的AR眼镜显示方案,核心结构通常由光机、波导和耦合器组成。光机内的微型显示…...

SpringBoot(十九)创建多模块Springboot项目(完整版)
之前我有记录过一次SpringBoot多模块项目的搭建,但是那一次只是做了一个小小的测试。只是把各模块联通之后就结束了。 最近要增加业务开发,要将目前的单模块项目改成多模块项目,我就参照了一下我上次搭建的流程,发现总是有报错。上次搭建的比较顺利,很多细枝末节也没有仔细…...
Navicat 17 功能简介 | 单元格编辑器
Navicat 17 功能简介 | 单元格编辑器 本期,我们一起了解 Navicat 17 出色的数据操作功能的单元格编辑器。单元格编辑器支持文本、十六进制、图像和网页四种格式的数据编辑,位于底部的编辑器窗格,为你编辑更大容量的数据信息提供足够的显示和操…...
MySQL【四】
插入数据 向数据表中插入一行数据 INSERT|REPLACE INTO 表名[(字段列表)] VALUES(值列表); ########## 在s表中插入一条记录:学号为s011,姓名为李思,性别为默认值,计算机专业 ########## insert into s(sno,sname,dept)values(s011,李思,计…...
简单叙述 Spring Boot 启动过程
文章目录 1. 准备阶段:应用启动的入口2. 创建 SpringApplication 对象:开始启动工作3. 配置环境(Environment):识别开发环境与生产环境4. 启动监听器和初始化器:感知启动的关键事件5. 创建 ApplicationCont…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...

Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...