Mybatis 批量插入
一、首先对于批量数据的插入有两种解决方案(下面内容只讨论和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
Mybatis 批量插入的更多相关文章
- mybatis批量插入数据到oracle
mybatis 批量插入数据到oracle报 ”java.sql.SQLException: ORA-00933: SQL 命令未正确结束“ 错误解决方法 oracle批量插入使用 insert a ...
- springMVC 接收数组参数,mybatis 接收数组参数,mybatis批量插入/批量删除案例
案例是给一个用户赋予多个权限,多个权限用其对应的主键 id 为参数,组成了 一个id数组,传给springMVC,然后springMVC传给mybatis,然后mybatis批量插入.其实类似的场景还 ...
- 解决Oracle+Mybatis批量插入报错:SQL 命令未正确结束
Mybatis批量插入需要foreach元素.foreach元素有以下主要属性: (1)item:集合中每一个元素进行迭代时的别名. (2)index:指定一个名字,用于表示在迭代过程中,每次迭代到的 ...
- 160421、MyBatis批量插入数据
在程序中封装了一个List集合对象,然后需要把该集合中的实体插入到数据库中,由于项目使用了Spring+MyBatis的配置,所以打算使用MyBatis批量插入,由于之前没用过批量插入,在网上找了一些 ...
- MyBatis批量插入数据(MySql)
由于项目需要生成多条数据,并保存到数据库当中,在程序中封装了一个List集合对象,然后需要把该集合中的实体插入到数据库中,项目使用了Spring+MyBatis,所以打算使用MyBatis批量插入,应 ...
- mybatis批量插入oracle时报错:unique constraint (table name) violated
mybatis批量插入oracle时报错:unique constraint (table name) violated,是因为插入的集合中有两条相同唯一约束的数据.
- Mybatis 批量插入数据
--mybatis 批量插入数据 --1.Oracle(需要测试下是否支持MySQL) < insert id ="insertBatch" parameterType=&q ...
- 【mybatis批量插入】
mybatis批量插入操作: MySQL:1.INSERT INTO TABLE_NAME(ID,NAME)VALUES(1,'张三'),(2,'李四') 2.INS ...
- mybatis批量插入、批量删除
mybatis 批量插入 int addBatch(@Param("list")List<CustInfo> list); <insert id="ad ...
- 【转载】MyBatis批量插入数据(insert)
介绍:MyBatis批量插入数据,原理就是在xml文件中添加 foreach 语句,然后MyBatis自动在values后面添加多个括号: XML文件如下: <?xml version=&quo ...
随机推荐
- java容器之HashMap
HashMap采用了数组和链表的数据结构,能在查询和修改方便继承了数组的线性查找和链表的寻址修改,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的. 解决哈希冲突的三个方法: a.开放 ...
- 🔥完美解决ESlint+Prettier各项配置冲突的语法报错问题(新手向)
本文重点: 1.解决修改了Prettier默认配置,项目内格式化无法生效 2.解决Prettier缺少配置,函数名和括号之间,自动添加空格 3.settings.json配置项分享 一个程序员,可能非 ...
- LeetCode Weekly Contest 266
第一题 题解:模拟题 class Solution { public: int countVowelSubstrings(string w) { int n = w.length(); int i = ...
- 【java+selenium3】自动化cookie操作+图形验证码处理 (十五)
一.cookie操作 1.获取浏览器所有的cookie import java.util.Set; import org.openqa.selenium.Cookie; //获取浏览器所有的cooki ...
- Solon & Solon Cloud 1.5.62 发布,轻量级 Java 基础开发框架
Solon 已有120个生态扩展插件,此次更新主要为细节打磨,且对k8s和docker-compose更友好: 1.插件 solon.coud ,事件总线增加支持本地同主题多订阅模式(以支持同服务内, ...
- [python]django关闭debug
1.版本声明 python3.6.5 django2.0.6 2.打开项目-setting setting.py中DEBUG默认是等于True,这样的话当访问接口存在错误会直接展示项目的所有配置信息, ...
- 什么是齐博x1标签
X系列的标签跟V系列的标签区别还是很大的.在V系列的时候,只有一种很简单的标签比如$label[XXXX]以前的标签相对现在的来说太简单的点,所以在功能上也比较受限.X系列目前有几下几种标签 {qb: ...
- WinForm训练一_改变窗体大小
1 //引用系统命名空间 2 using System; 3 //项目命名空间 4 using System.Collections.Generic; 5 using System.Component ...
- Java培训机构如何选择才能避免被骗?
近年来,随着IT行业的快速崛起,各类互联网人才供不应求,而Java工程师作为目前最为火爆的岗位之一,更是以高薪+高新技术的标签受到了人们的广泛关注.许多年轻人也看到了这个行业的发展前景,决定报名培训机 ...
- [LCT学习时的一些笔记]
会找时间写一篇学习笔记的. \(Access\)的操作是把\(x\)和\(x\)所在原树的顶端点的路径变为一个\(splay\) 对于原树边我们有这样的操作,对每个\(splay\)的顶点维护一个父亲 ...