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 会分批次插入所以每批次会有一个事物,提交也是一个批次一起提交,回滚也只回滚一个批次

奋斗不止,进步无止境,让人生在追求中焕发光彩!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/59674.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Thinkphp6视图介绍

一.MVC MVC 软件系统分为三个基本部分&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controller&#xff09; ThinkPHP6 是一个典型的 MVC 架构 控制器—控制器&#xff0c;用于将用户请求转发给相应的Model进行处理&a…

C++(Qt)软件调试---内存泄漏分析工具MTuner (25)

C(Qt)软件调试—内存泄漏分析工具MTuner &#xff08;25&#xff09; 文章目录 C(Qt)软件调试---内存泄漏分析工具MTuner &#xff08;25&#xff09;[toc]1、概述&#x1f41c;2、下载MTuner&#x1fab2;3、使用MTuner分析qt程序内存泄漏&#x1f9a7;4、相关地址&#x1f41…

QT_CONFIG宏使用

时常在Qt代码中看到QT_CONFIG宏&#xff0c;之前以为和#define、DEFINES 差不多&#xff0c;看了定义才发现不是那么回事&#xff0c;定义如下&#xff1a; 看注释就知道了QT_CONFIG宏&#xff0c;其实是&#xff1a;实现了一个在编译时期安全检查&#xff0c;检查指定的Qt特性…

Redis下载历史版本

Linux版本&#xff1a; https://download.redis.io/releases/ Windows版本&#xff1a; https://github.com/tporadowski/redis/releases Linux Redis对应gcc版本

8 软件项目管理

软件项目管理 1、软件项目管理概念1.1 软件项目管理内容1.2 软件项目管理的4P要素人员产品过程项目 2、软件项目度量2.1 软件项目度量定义及度量方法2.2 面对规模的度量2.3 面对功能的度量UFC相关的五类组件14个复杂性调节因素 F i F_i Fi​一个功能点开发代码行数 2.4 软件估算…

游戏引擎学习第12天

视频参考:https://www.bilibili.com/video/BV1yom9YnEWY 这节没讲什么东西&#xff0c;主要是改了一下音频的代码 后面有介绍一些alloc 和malloc,VirtualAlloc 的东西 _alloca 函数&#xff08;或 alloca&#xff09;分配的是栈内存&#xff0c;它的特点是&#xff1a; 生命周…

如何保证Redis与MySQL双写一致性

什么是双写一致性问题&#xff1f; 双写一致性主要指在一个数据同时存在于缓存&#xff08;如Redis&#xff09;和持久化存储&#xff08;如MySQL&#xff09;的情况下&#xff0c;任何一方的数据更新都必须确保另一方数据的同步更新&#xff0c;以保持双方数据的一致状态。这一…

STM32设计学生宿舍监测控制系统

目录 前言 一、本设计主要实现哪些很“开门”功能&#xff1f; 二、电路设计原理图 电路图采用Altium Designer进行设计&#xff1a; 三、实物设计图 四、程序源代码设计 五、获取资料内容 前言 随着科技的飞速发展和智能化时代的到来&#xff0c;学生宿舍的安全、舒适…

算法--解决二叉树遍历问题

第一 实现树的结构 class Node(): # 构造函数&#xff0c;初始化节点对象&#xff0c;包含数据和左右子节点 def __init__(self, dataNone): self.data data # 节点存储的数据 self.left None # 左子节点&#xff0c;默认为None self.rig…

【C#】C#编程入门指南:构建你的.NET开发基础

文章目录 前言&#xff1a;1. C# 开发环境 VS的基本熟悉2. 解决方案与项目的关系3. 编辑、编译、链接、运行4. 托管代码和CLR4.1 CLR&#xff1a;4.2 C# 代码第编译过程&#xff08;两次编译的&#xff09; 5. 命名空间6. 类的组成与分析7. C# 的数据类型7.1 值类型7.2 引用类型…

算法闭关修炼百题计划(八)

一半来自力扣的push题单 1.最大连续1的个数II2.长度为k的无重复字符子串3.句子的相似性4.移位字符串分组5.x的平方根6.Z字形变换 1.最大连续1的个数II 给定一个二进制数组nums&#xff0c;如果最多可以翻转一个0&#xff0c;则返回数组中连续1的最大个数 之前是Window&#x…

论文笔记(五十六)VIPose: Real-time Visual-Inertial 6D Object Pose Tracking

VIPose: Real-time Visual-Inertial 6D Object Pose Tracking 文章概括摘要I. INTRODACTIONII. 相关工作III. APPROACHA. 姿态跟踪工作流程B. VIPose网络 文章概括 引用&#xff1a; inproceedings{ge2021vipose,title{Vipose: Real-time visual-inertial 6d object pose tra…

K8S containerd拉取harbor镜像

前言 接前面的环境 K8S 1.24以后开始启用docker作为CRI&#xff0c;这里用containerd拉取 参考文档 正文 vim /etc/containerd/config.toml #修改内容如下 #sandbox_image "registry.aliyuncs.com/google_containers/pause:3.10" systemd_cgroup true [plugins.…

LM2 : A Simple Society of Language Models Solves Complex Reasoning

文章目录 题目摘要简介相关工作方法论实验结果结论局限性 题目 LM2&#xff1a;简单的语言模型社会解决复杂推理问题 论文地址&#xff1a;https://aclanthology.org/2024.emnlp-main.920/ 项目地址&#xff1a; https://github.com/LCS2-IIITD/Language_Model_Multiplex 摘要…

STM32从上电开始启动过程详解(上电->分散加载->main函数)

1.硬件复位之后&#xff0c;CPU 内的时序逻辑电路首先完成如下两个工作&#xff08; 程序代码下载到内部 flash 为例&#xff0c;flash首地址 0x0800 0000&#xff09;  将 0x08000000 位置存放的堆栈栈顶地址存放到 SP 中(MSP)。  将 0x08000004 位置存放的向量地址装入 P…

新版Apache tomcat服务安装 Mac+Window双环境(笔记)

简介&#xff1a;Tomcat服务器器的下载和安装&#xff1a; 安装前提 1&#xff09;电脑需要有java环境&#xff0c;jdk8以上&#xff0c;否则启动不不成功 2&#xff09;已经安装Sublime⽂文件编辑软件 3&#xff09;window电脑需要显示⽂文件拓拓展名 官网&#xff08;https:…

数据重塑:长宽数据转换【基于tidyr】

在数据分析和可视化过程中&#xff0c;数据的组织形式直接影响着我们能够进行的分析类型和可视化效果。这里简单介绍两种常见的数据格式&#xff1a;长格式&#xff08;Long Format&#xff09;和宽格式&#xff08;Wide Format&#xff09;&#xff0c;以及如何使用tidyr包进行…

ollama+springboot ai+vue+elementUI整合

1. 下载安装ollama (1) 官网下载地址&#xff1a;https://github.com/ollama/ollama 这里以window版本为主&#xff0c;下载链接为&#xff1a;https://ollama.com/download/OllamaSetup.exe。 安装完毕后&#xff0c;桌面小图标有一个小图标&#xff0c;表示已安装成功&…

基于lighthouse搭建私有网盘Cloudreve【开源应用实践】

基于lighthouse搭建私有网盘Cloudreve【超高性价比】 今天给大家分享一款私人网盘神器&#xff0c;既能存放你的文件文档&#xff0c;也能替你保存那不可告人的秘密~ 香菇今天将手把手教给大家如何在腾讯云轻量应用服务器上搭建个人专属网盘 1. 既爱又恨的网盘存储 很多小伙伴…

JavaScript高级篇 - 浏览器事件详解 DOM事件以及独立封装事件Util和Ajax封装

Dom事件 Model&#xff08;特定领域对象的抽象&#xff09;、Protocal&#xff08;针对数据格式的约定&#xff09; DOM(Document Object Model&#xff0c;文档对象模型)是针对HTML文档和XML文档的一个API。DOM描绘了一个层次化的节点树&#xff0c;允许开发人员添加、移出和…