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

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优化

数据库批量入库方常见方式&#xff1a;Java中foreach和xml中使用foreach 两者的区别&#xff1a; 通过Java的foreach循环批量插入&#xff1a; 当我们在Java通过foreach循环插入的时候&#xff0c;是一条一条sql执行然后将事物统一交给spring的事物来管理&#xff08;Transa…...

Word VBA如何间隔选中多个(非连续)段落

实例需求&#xff1a;Word文档中的有多个段落&#xff0c;段落总数量不确定&#xff0c;现在需要先选中所有基数段落&#xff0c;即&#xff1a;段落1&#xff0c;段落3 … &#xff0c;然后一次性设置粗体格式。 也许有的读者会认为这个无厘头的需求&#xff0c;循环遍历遍历文…...

Linux系统常用操作与命令指南

一、快捷分类 1、移动光标 h&#xff0c; j&#xff0c; k&#xff0c; l 左&#xff0c; 下&#xff0c; 上&#xff0c; 右 Ctrl-F:下翻一页 Ctrl-B:上翻一页 Ctrl-U:上翻半页 Ctrl-d:下翻半页 0:跳至行首&#xff0c;不管有无缩进&#xff0c;就是跳到第0个字…...

StructuredStreaming (一)

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

由播客转向个人定制的音频频道(1)平台搭建

项目的背景 最近开始听喜马拉雅播客的内容&#xff0c;但是发现许多不方便的地方。 休息的时候收听喜马拉雅&#xff0c;但是还需要不断地选择喜马拉雅的内容&#xff0c;比较麻烦&#xff0c;而且黑灯操作反而伤眼睛。 喜马拉雅为代表的播客平台都是VOD 形式的&#xff0…...

[自然语言处理] [AI]深入理解语言与情感分类:从基础到深度学习的进展

语言是人类智能的核心组成部分,具有极高的复杂性和多样性。理解语言,尤其是语言中的隐含部分,向来是人工智能研究的一个巨大挑战。图灵测试本身便是一场关于语言生成与理解的比赛,旨在检验机器是否能够模拟人类的语言能力。随着深度学习的飞速发展,语音识别、情感分析等自…...

【GPTs】Gif-PT:DALL·E制作创意动图与精灵动画

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 &#x1f4af;GPTs指令&#x1f4af;前言&#x1f4af;Gif-PT主要功能适用场景优点缺点 &#x1f4af;小结 &#x1f4af;GPTs指令 中文翻译&#xff1a; 使用Dalle生成用户请求的精灵图动画&#…...

云原生周刊:Istio 1.24.0 正式发布

云原生周刊&#xff1a;Istio 1.24.0 正式发布 开源项目推荐 Kopf Kopf 是一个简洁高效的 Python 框架&#xff0c;只需几行代码即可编写 Kubernetes Operator。Kubernetes&#xff08;K8s&#xff09;作为强大的容器编排系统&#xff0c;虽自带命令行工具&#xff08;kubec…...

Linux设置jar包开机启动

操作系统环境&#xff1a;CentOS 7 【需要 root 权限&#xff0c;使用 root 用户进行操作 或 普通用户使用 sudo 进行操作】 一、系统服务的方式 原理&#xff1a;利用系统服务管理应用程序的生命周期&#xff0c; systemctl 为系统服务管理工具 systemctl start applicati…...

计算机视觉和机器人技术中的下一个标记预测与视频扩散相结合

一种新方法可以训练神经网络对损坏的数据进行分类&#xff0c;同时预测下一步操作。 它可以为机器人制定灵活的计划&#xff0c;生成高质量的视频&#xff0c;并帮助人工智能代理导航数字环境。 Diffusion Forcing 方法可以对嘈杂的数据进行分类&#xff0c;并可靠地预测任务的…...

C语言之简单的获取命令行参数和环境变量

C语言之简单的获取命令行参数和环境变量 本人的开发环境为WIN10操作系统用VMWARE虚拟的UBUNTU LINUX 18.04LTS&#xff01;&#xff01;&#xff01; 所有代码的编辑、编译、运行都在虚拟机上操作&#xff0c;初学的朋友要注意这一点&#xff01;&#xff01;&#xff01; 详细…...

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的修改操作 &#x1f493; 博客主页&#xff1a;C-SDN花园GGbond ⏩ 文章专栏…...

SystemVerilog学习笔记(一):数据类型

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

Linux软件包管理与Vim编辑器使用指南

目录 一、Linux软件包管理器yum 1.什么是软件包&#xff1f; 2.什么是软件包管理器&#xff1f; 3.查看软件包 4.安装软件 ​编辑 5.卸载软件 Linux开发工具&#xff1a; 二、Linux编辑器---vim 1.vim的基本概念 (1) 正常/普通模式&#xff08;Normal mode&#xff0…...

每日一练 | 包过滤防火墙的工作原理

01 真题题目 包过滤防火墙对哪一层的数据报文进行检查&#xff1f; A. 应用层 B. 物理层 C. 网络层 D. 链路层 02 真题答案 C 03 答案解析 包过滤防火墙是一种基本的安全设备&#xff0c;它通过检查进出网络的数据包来决定是否允许该数据包通过。 这种类型的防火墙主要关注…...

AR眼镜方案_AR智能眼镜阵列/衍射光波导显示方案

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

SpringBoot(十九)创建多模块Springboot项目(完整版)

之前我有记录过一次SpringBoot多模块项目的搭建,但是那一次只是做了一个小小的测试。只是把各模块联通之后就结束了。 最近要增加业务开发,要将目前的单模块项目改成多模块项目,我就参照了一下我上次搭建的流程,发现总是有报错。上次搭建的比较顺利,很多细枝末节也没有仔细…...

Navicat 17 功能简介 | 单元格编辑器

Navicat 17 功能简介 | 单元格编辑器 本期&#xff0c;我们一起了解 Navicat 17 出色的数据操作功能的单元格编辑器。单元格编辑器支持文本、十六进制、图像和网页四种格式的数据编辑&#xff0c;位于底部的编辑器窗格&#xff0c;为你编辑更大容量的数据信息提供足够的显示和操…...

MySQL【四】

插入数据 向数据表中插入一行数据 INSERT|REPLACE INTO 表名[(字段列表)] VALUES(值列表); ########## 在s表中插入一条记录&#xff1a;学号为s011,姓名为李思&#xff0c;性别为默认值&#xff0c;计算机专业 ########## insert into s(sno,sname,dept)values(s011,李思,计…...

简单叙述 Spring Boot 启动过程

文章目录 1. 准备阶段&#xff1a;应用启动的入口2. 创建 SpringApplication 对象&#xff1a;开始启动工作3. 配置环境&#xff08;Environment&#xff09;&#xff1a;识别开发环境与生产环境4. 启动监听器和初始化器&#xff1a;感知启动的关键事件5. 创建 ApplicationCont…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...