Mybatis 批量插入事物问题_狂奔的蜗牛Evan的博客-程序员秘密

技术标签: mybatis  事物  批量插入  ORM  

一、首先对于批量数据的插入有两种解决方案(下面内容只讨论和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

https://blog.csdn.net/qq_39275746/article/details/86488443

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lisheng19870305/article/details/103814569

智能推荐

手柄映射软件_【手柄教程】崩坏2手柄按键映射以及设置教程_weixin_39805734的博客-程序员秘密

最近刚开始用雷电,喜欢这款模拟器可以自定义IMEI的功能.对一些手游的支持性也比别的模拟器要强废话不多说,干货送上我用的手柄映射软件是Xpadder.虽然这款软件比较老,但是软件的功能强大,对各个厂商的手柄支持性也比较好软件界面设置界面不过在按键的编写,特别是宏按键上,设置比较复杂.这里附上我自己的模拟器按键键位设置以及按键映射宏 希望对大家有个启发.模拟器按键设置附图手柄对应按键以及宏...

< Unity 3D专栏 >添加控件检测事件,函数处理_unity 检测并添加组件_鱼C缸的博客-程序员秘密

注册一个函数时间,用来监控button是否被按下。 void Start () { Transform skill_back = transform.Find("button_back"); UIEventListener.Get(skill_back.gameObject).onClick = OnSkillback;} void OnSkillback(

AIDA64内存与缓存测试过了算稳定吗_KLEVV BLOT XR DDR4内存:锐龙平台兼容性测试_weixin_39670246的博客-程序员秘密

来自韩国 SK 集团旗下的 科赋 Essencore KLEVV 在 BOLT 系列又有新产品,这回带来的是 BLOT XR 系列,相较于先前推出的 BOLT 系列除了拥有更高的频率选择以外,在散热片上更是有着更为加强的设计,整体采用纯铝金属材质的沉稳散热片,并搭配特色的花纹,呈现出低调沉稳的风格特色。此外,BLOT XR 同时也在 AMD Ryzen 平台上通过相关的兼容性测试,对于近期 AMD...

《SICP》习题第1章_阿团团的博客-程序员秘密

本人做的SICP习题第1章,如有错误请指正,用的解释器是Racket 练习1.1计算代码如下;; Exercise 1.1#lang racket10(+ 5 3 4)(- 9 1)(/ 6 2)(+ (* 2 4) (- 4 6))(define a 3)(define b (+ a 1))(+ a b (* a b))(= a b)(i...

随便推点

MySQL/MariaDB高可用架构之MHA_mysql mha架构图_AhhSong的博客-程序员秘密

MariaDB/MySQL数据库、MHA(Master HA)、主从复制架构

MySQL高级-SQL优化_Java硬件工程师的博客-程序员秘密

1.大批量插入数据环境准备 :CREATE TABLE `tb_user_1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(45) NOT NULL, `password` varchar(96) NOT NULL, `name` varchar(45) NOT NULL, `birthday` datetime DEFAULT NULL, `sex` char(1) DEFAULT NULL, `em

MVC5发布到IIS,出现HTTP 错误 404.0 - Not Found的完美解决方法_weixin_34088598的博客-程序员秘密

今天把mvc5发布到IIS,出现了HTTP 错误 404.0 - Not Found。一般有两个方案。我试试了一种无效,而且也不是最优方案,所以我推荐方案二。一、解决方案一在MVC根目录的web.config中添加&lt;system.webServer&gt;&lt;modules runAllManagedModulesForAllRequests="true" /&...

SSM框架开发应用(二)——MyBatis框架介绍_Undergoer_TW的博客-程序员秘密

MyBatis框架介绍一、数据持久化概念数据持久化是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的过程。例如,文件的存储、数据的读取等都是数据持久化操作。数据模型可以是任何数据结构或对象模型,存储模型可以是关系模型、XML、二进制流等。从以上的概念描述,我们思考一下,之前是否接触过数据持久化?是否做过数据持久化的操作?答案是肯定的,从一开始,我们就编写应用程序...

atom对比 vscode_vs code & Atom 对比使用心得_织围巾的小仙女的博客-程序员秘密

作为一名前端工程师,一个好的编辑器可以在编码期间,事半功倍。这里我分享一下vs code和atom这两种现今非常流行的编辑器,各有各的优缺点,看大家的喜好。我比较倾向于vs code,顺便也把插件整理了一下,给大家分享。vs codevs code是微软公司出的,之前我一直以为vs code像visual studio一样,非常大,而且每次启动非常慢。但是一用就错了,启动秒级速度,这次微软也算是对...

推荐文章

热门文章

相关标签