需要注意的 Mybatis 批量插入

2023-11-01

一、首先对于批量数据的插入有两种解决方案(下面内容只讨论和Mysql交互的情况)

1)for循环调用Dao中的单条插入方法

2)传一个List<Object>参数,使用Mybatis的批量插入 (foreach)

对于批量插入它的Mapper看起来向这样

<insert id="addUser" parameterType="java.util.List" >
insert into user(name,age) values
    <foreach collection="list" item="item" index="index" separator=",">
        (#{item.name},#{item.age})
    </foreach>
</insert>

 

二、这两种方案首先在性能上,肯定是批量插入性能好,更加省时间。

原因如下:

  • 循环插入:需要每次都获取session,获取连接,然后将sql 语句发给mysql 去执行(JDBC一般情况下是通过TCP/IP 进行连接和数据库进行通信的)。可以看这里 mysql四种通信协议
  • 批量插入: 批量插入通过foreach 标签,将多条数据拼接在sql 语句后,一次执行只获取一次session,提交一条sql语句。减少了程序和数据库交互的准备时间。

 

三、但是批量插入有需要注意的地方:

1、首先是返回值

对于普通的单条插入,数据库的返回值就是 (0/1) 。

对于返回值代表的意思可以认为是

“语句执行返回的数据库受影响的行数。”

或者是

“此次执行是否成功(0-失败,1-成功)。”

对应的也就是在Dao层中,对于插入方法的返回值类型的设定有(int/boolean)两种

 

对于批量插入的返回值,返回的还是(0/1),而不是统计插入成功几条,即使你的Dao层方法的返回值类型为int.

这里的(0/1) 也就代表着,这次批量插入是否成功(0-失败,1-成功)。

当然你Dao层的返回值还是可以是(int/boolean)

 

2、对于批量插入中间有一个失败会怎么样

猜想有下面三种情况

a、继续插入后面的,把失败的跳过

b、停止插入,但前面的插入成功保持。

c、全部回滚

这里就直接放结果了。

批量语句,只要有一个失败,就会全部失败。数据库会回滚全部数据。

关于测试过程可以看这篇博客:mysql批量插入语句执行失败的话,是部分失败还是全部失败

 

其实也很好理解。

首先我们知道了mybatis <foreache>批量插入,是在程序内拼接sql 语句(拼接成多条同时插入的sql语句),拼接后发给数据库。

就相当于咱们自己在mysql的命令行中,执行一条多插入的语句。默认情况下 mysql 单条语句是一个事务,这在一个事务范围内,当中间的sql语句有问题,或者有一个插入失败,就会触发事务回滚。同时你也能看到错误提示。(命令行执行单条sql的情况)

所以有一个插入不成功肯定全部回滚。

 

3、批量插入数据量的限制

我这里就直接放结论,又兴趣的可以看这篇博客有探究过程 : Mybatis 批量插入引发的血案

1)、Mybatis 本身对插入的数据量没有限制

2)、mysql对语句的长度有限制,默认是 4M

其他数据库的情况这里不介绍,可以自行百度。通过上面 “mysql对语句的长度有限制,默认是 4M” 我们可以知道,批量插入数据是有限制的。不能一下把几万条数据(就是太大数据量意思)一次性插入。

所以一般情况下我们推荐即使使用批量插入,也要分批次。

每次批次设置多少?需要根据你的插入一条数据的参数量来做度量。因为受限条件是sql语句的长度。

而且分批插入更加合理,对于插入失败,回滚范围会缩小很多。

 

4、为了保证程序健壮性,对空集合参数的校验

Mybatis并没有做集合容量的验证,如果集合参数为空或者size为0则生成的sql可能只有”insert into user(name,age) values”这样一段或者没有,所以说,写批量sql的时候注意在调用批量方法的地方加入对容量的验证。

 

5、mybatis批量插入的另外一种不推荐的写法
<insert id="addBatchUser" parameterType="java.util.List" >
    <foreach collection="list" item="item" index="index" separator=";">
        insert into user(name,age) values(#{item.name},#{item.age})
    </foreach>
</insert>

 

这种写法也能实现批量插入。但是有很多问题。

a、首先这种方式的批量插入也是sql拼接。但是明显字符长度增加。这就导致每批次可插入的数量减少

b、这种方式执行返回值还是(0、1)是已经尝试插入的最后一条数据是否成功。由于这种foreach 拼接成的sql语句,是以分号“;”分隔的多条insert语句。这就导致前面的数据项都插入成功了。(默认数据库的事务处理是单条提交的,出错前的执行都是一个个单条语句,所以并并没有回滚数据。)

所以如果你想中间插入失败回滚的话,需要使用Spring事务,但是还需要注意spring事务是抛出运行时异常时才会回滚。这种批量插入中间有没插入成功的是不会抛出异常的。所以你需要根据返回值判断手动编码抛出异常。

而最上面的那种写法就不用是用事务,因为他是一条sql语句。

 

四、补充 :<foreach>中参数的介绍

foreach简介
foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。
foreach元素的属性主要有 item,index,collection,open,separator,close。
item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔 符,close表示以什么结束,在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的,主要有一下3种情况:

  • 1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
  • 2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
  • 3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map

以上内容为自己总结,难免会有疏漏,如有错误还请指出。不胜感谢!

转载于:https://my.oschina.net/zjllovecode/blog/1818716

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

需要注意的 Mybatis 批量插入 的相关文章

随机推荐

  • 常用正则表达式例子

    原文 http blog sina com cn s blog 4c646b600100evq3 html 1 d 匹配非负整数 正整数 0 2 0 9 1 9 0 9 匹配正整数 3 d 0 匹配非正整数 负整数 0 4 0 9 1 9
  • 【蓝桥杯】第十四届蓝桥杯模拟赛(第三期)C++ (弱go的记录,有问题的话求指点)

    博主是菜鸡啦 代码仅供参考 只确定能过样例 嘻嘻 第一题 填空题 问题描述 请找到一个大于 2022 的最小数 这个数转换成十六进制之后 所有的数位 不含前导 0 都为字母 A 到 F 请将这个数的十进制形式作为答案提交 答案提交 这是一道
  • css的list,CSS List 入门教程

    CSS List 入门教程 list指得是在css中的li等标签的控制了 面list也有四个属性 其实有五个我们只讲常用的4个了 他们分别为 list style list style image list style position l
  • 【thinkphp5学习笔记之一 】安装

    一 安装composer 1 点此下载composer 然后运行 2 打开cmd 按行分别输入以下代码 要求php安装并且路径配置完毕 php r copy https install phpcomposer com installer c
  • 51单片机实战教程之C语言基础(二 C语言运算符)

    Keil C51基础之运算符详解 一 算术运算符 包括加 减 乘 除 取模 自加 自减 示例 5 3 结果 2 char a 5 a 结果 5 1 a为6 a 结果 6 1 a为 5 二 关系运算符 包括小于 lt 小于等于 lt 大于 g
  • Chrome 截图页面全图

    打开谷歌浏览器 按F12 弹出开发者工作 开发者工具中 按下快捷键组合Ctrl Shift P Windows 在命令行中输入 Screen 可以看到三个选项 根据不同需求进行选择 具体如下图所示 整个网页 Capture full siz
  • 圆周率 π 是否隐藏了本个宇宙的设计者留给这个宇宙的智慧文明的某种信息?...

    还是太naive了 我要是宇宙设计者 我就把信息藏在蔡廷常数里 这才是对人类最大的嘲讽 蔡廷常数 其含义是找随机生成一段程序 这段程序不会陷入死循环的概率 可以证明这是一个确定存在的无理数 但是同样可以证明它是不可以被计算出来的 实际上 能
  • LeetCode:58. 最后一个单词的长度

    给你一个字符串 s 由若干单词组成 单词前后用一些空格字符隔开 返回字符串中 最后一个 单词的长度 单词 是指仅由字母组成 不包含任何空格字符的最大子字符串 示例 1 输入 s Hello World 输出 5 解释 最后一个单词是 Wor
  • 'umi' 不是内部或外部命令

    1 首先 需要安装Node js 一路下一步安装 并确保 node 版本是 8 10 或以上 mac 下推荐使用 nvm 来管理 node 版本 安装完成后 通过node v 命令查看其版本号 2 推荐使用 yarn 管理 npm 依赖 并
  • Unity批量预设体替换材质球

    using System Collections using System Collections Generic using UnityEditor using UnityEngine using UnityEngine UI using
  • linux查看端口的使用情况

    lsof 查看端口占用语法格式 lsof i 端口号 lsof i 8080 查看8080端口占用 lsof abc txt 显示开启文件abc txt的进程 lsof c abc 显示abc进程现在打开的文件 lsof c p 1234
  • docker配置文件挂载(容器数据管理)

    目录 数据卷 容器数据管理 什么是数据卷 数据集操作命令 创建和查看数据卷 挂载数据卷 案例 案例 给nginx挂载数据卷 案例 给MySQL挂载本地目录 总结 数据卷 容器数据管理 在之前的nginx案例中 修改nginx的html页面时
  • 大数据平台测试-后端代码覆盖率工具

    一 后端覆盖率工具 在后端开发中 常用的覆盖率工具包括 JaCoCo Java Code Coverage JaCoCo 是一个流行的 Java 代码覆盖率工具 它可以在编译期间插入字节码 收集覆盖率信息 并生成报告 JaCoCo 支持行覆
  • VScode react @ import引入路径智能提示

    1 安装Path Intellisense插件 2 在settings json中配置 path intellisense mappings workspaceRoot src 3 在项目package json所在同级目录下创建文件jsc
  • Object Detection

    目标检测神文 非常全而且持续在更新 转发自 https handong1587 github io deep learning 2015 10 09 object detection html 如有侵权联系删除 我会跟进原作者博客持续更新
  • TransactionTemplate 事务编程式写法

    建议使用声明式事务 Transactional rollbackFor Exception class 粒度不够 拆分方法 import org springframework transaction support Transaction
  • 题目68 求随机整书数组中两个数和绝对值最小值(ok)

    给定一个随机的整数数组 可能存在正整数和负整数 nums 请你在该数组中找出两个数 其和的绝对值 nums x nums y 为最小值 并返回这两个数 按从小到大返回 以及绝对值 每种输入只会对应一个答案 但是 数组中同一个元素不能使用两遍
  • Python(8):循环语句

    Python循环语句 今天重点学习关于循环的关键字 for while else ranage break continue pass while 一般形式 while 判断条件 condition 执行语句块statements 直接上代
  • 主成分分析Python代码

    对于主成分分析详细的介绍 主成分分析 PCA 原理详解https blog csdn net zhongkelee article details 44064401 import numpy as np import pandas as p
  • 需要注意的 Mybatis 批量插入

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 一 首先对于批量数据的插入有两种解决方案 下面内容只讨论和Mysql交互的情况 1 for循环调用Dao中的单条插入方法 2 传一个List参数 使用Mybatis的批量插