mybatis批量插入的四种方式
一、循环插入
public void insert(List<User> userList) {
userList.forEach(user -> userDao.insert(user));
}
<insert id="insert">
INSERT INTO `demo`.`user` (`username`, `address`, `remark`, `age`, `create_time`)
VALUES (#{user.username,jdbcType=VARCHAR},
#{user.address,jdbcType=VARCHAR},
#{user.remark,jdbcType=VARCHAR},
#{user.age,jdbcType=INTEGER},
now())
</insert>
二、批量插入
这里是否选择100个为一组还是200或者其他,需要进行多次测试
public void insertBatch(List<User> userList) {
List<List<User>> partition = ListUtil.partition(userList, 100);
for (List<User> users : partition) {
userDao.insertBatch(users);
}
}
<insert id="insertBatch">
INSERT INTO `demo`.`user` (`username`, `address`, `remark`, `age`, `create_time`)
VALUES
<foreach collection="users" index="" item="user" separator=",">
(#{user.username,jdbcType=VARCHAR},
#{user.address,jdbcType=VARCHAR},
#{user.remark,jdbcType=VARCHAR},
#{user.age,jdbcType=INTEGER},
now())
</foreach>
</insert>
三、BatchExecutor插入
mybatis提供了三种sql执行器,分别是SIMPLE(默认),REUSE,BATCH:
- SIMPLE(SimpleExecutor),相当于JDBC的
PreparedStatement.execute(sql)执行完毕即关闭即PreparedStatement.close() - REUSE(ReuseExecutor),相当于JDBC的
PreparedStatement.execute(sql)执行完不关闭,而是将PreparedStatement存入 Map<String, Statement>中缓存,其中key为执行的sql模板; - BATCH(BatchExecutor),相当于JDBC语句的
PreparedStatement.addBatch(sql),即仅将执行SQL加入到批量计划但是不真正执行, 所以此时不会执行返回受影响的行数,而只有执行PreparedStatement.execteBatch()后才会真正执行sql
@Autowired
private SqlSessionFactory sqlSessionFactory;
@Override
public void insertBatchType(List<User> userList) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
UserDao mapper = sqlSession.getMapper(UserDao.class);
try {
for (User user : userList) {
mapper.insert(user);
}
sqlSession.commit();
} catch (Exception e) {
System.out.println("批量导入数据异常,事务回滚");
sqlSession.rollback();
} finally {
sqlSession.close();
}
}
四、JDBC插入
当然也可以使用原生的JDBC的方式进行批量插入,使用` statement.addBatch();的方式,也是很快的
@Resource(name = "dataSource")
private DataSource dataSource;
@Override
public void insertJdbc(List<User> userList) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = dataSource.getConnection();
connection.setAutoCommit(false);
String sql = "INSERT INTO `user` (`username`, `address`, `remark`, `age`, `create_time`) " +
"VALUES (?,?,?,?,now()) ";
statement = connection.prepareStatement(sql);
for (User user : userList) {
statement.setString(1, user.getUsername());
statement.setString(2, user.getAddress());
statement.setString(3, user.getRemark());
statement.setInt(4, user.getAge());
statement.addBatch();
}
statement.executeBatch();
connection.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
statement.close();
connection.close();
}
}
五、测试效率
准备60w条数据,分别测试以上四种插入方式的效率:
@Test
public void test_for_user() throws SQLException {
List<User> userList = new ArrayList<>();
for (int i = 0; i < 600000; i++) {
User user = new User();
user.setUsername("张三" + i);
user.setAddress("上海" + i);
user.setRemark("备注" + i);
user.setAge(i);
userList.add(user);
}
StopWatch stopWatch = new StopWatch();
stopWatch.start("循环插入");
userService.insert(userList);
stopWatch.stop();
System.out.println(stopWatch.getLastTaskName() + ":" + stopWatch.getLastTaskTimeMillis());
stopWatch.start("批量插入");
userService.insertBatch(userList);
stopWatch.stop();
System.out.println(stopWatch.getLastTaskName() + ":" + stopWatch.getLastTaskTimeMillis());
stopWatch.start("BatchType插入");
userService.insertBatchType(userList);
stopWatch.stop();
System.out.println(stopWatch.getLastTaskName() + ":" + stopWatch.getLastTaskTimeMillis());
stopWatch.start("JDBC-BatchType插入");
userService.insertJdbc(userList);
stopWatch.stop();
System.out.println(stopWatch.getLastTaskName() + ":" + stopWatch.getLastTaskTimeMillis());
}
循环插入:1272111
批量插入:27990
BatchType插入:28143
JDBC-BatchType插入:15976
测试结果还是显而易见的,循环插入>批量插入>BatchType插入>JDBC批量插入
mybatis批量插入的四种方式的更多相关文章
- mybatis中批量插入的两种方式(高效插入)
MyBatis简介 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用 ...
- mybatis批量保存的两种方式(高效插入)
知识点:mybatis中,批量保存的两种方式 1.使用mybatis foreach标签 2.mybatis ExecutorType.BATCH 参考博客:https://www.jb51.net/ ...
- CSS插入的四种方式
一.什么是CSS CSS(Cascading style sheets 层叠样式表),CSS可以用以为网页构建样式表,通过样式表来达到对网页进行美化的效果.所谓层叠可以将网页想象成一层层的结构,高层 ...
- MyBatis_动态sql_foreach_mysql下foreach批量插入的两种方式
方法1: 笔记要点出错分析与总结工程组织数据库组织0.重新修改Bean类 修改1.定义接口 //批量插入 public void addEmps(@Param("emps") ...
- mybatis批量更新的几种方式和性能对比
https://blog.csdn.net/csdnbeyoung/article/details/106258611
- MyBatis 批量插入数据的 3 种方法!
批量插入功能是我们日常工作中比较常见的业务功能之一,之前我也写过一篇关于<MyBatis Plus 批量数据插入功能,yyds!>的文章,但评论区的反馈不是很好,主要有两个问题:第一,对 ...
- C#批量插入数据到Sqlserver中的四种方式
我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...
- C#_批量插入数据到Sqlserver中的四种方式
先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...
- C#批量插入数据到Sqlserver中的四种方式 - 转
先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...
- java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明)
转载地址:http://www.devba.com/index.php/archives/4581.html java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明); ...
随机推荐
- 样本数量不平衡问题方案(Focal Loss & Circle Loss)
1.Focal Loss focal loss是最初由何恺明提出的,最初用于图像领域解决数据不平衡造成的模型性能问题.本文试图从交叉熵损失函数出发,分析数据不平衡问题,focal loss与交叉熵损失 ...
- Python中局部放大图案例
例子一: 先上完整代码和效果图: import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1.ins ...
- 19.3 Boost Asio 多线程通信
多线程服务依赖于两个通用函数,首先boost::bind提供了一个高效的.简单的方法来创建函数对象和函数对象适配器,它的主要功能是提供了一种将函数和它的参数绑定到一起的方法,这种方法可以将具有参数的成 ...
- C/C++ Npcap包实现数据嗅探
npcap 是Nmap自带的一个数据包处理工具,Nmap底层就是使用这个包进行收发包的,该库,是可以进行二次开发的,不过使用C语言开发费劲,在进行渗透任务时,还是使用Python构建数据包高效,这东西 ...
- centOS系统 迁移docker镜像及数据文件到指定目录
话说我今天正在快乐的敲代码,突然看到IDE报警磁盘空间不足了,du -h 查看了一下磁盘占用情况,发现是自己的docker镜像全部放/var/lib/docker目录下 这个系统磁盘给根目录只分配了5 ...
- Git企业开发控制理论和实操-从入门到深入(二)|Git的基本操作
前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助. 高质量博客汇总https://blog.cs ...
- DNS反向解析
一:创建反向解析区 1.和创建正向解析区的步骤类似,选主要区域 这里设置的IP是192.168.1,一直点确定即可 2.指针记录即反向解析记录,记录ip对应的域名,是反向解析区最常用的记录 输入ip和 ...
- nginx 配置mp4文件播放
nginx 配置mp4文件播放 由于工作需要一个离线的视频播放地址,就想简单一点直接把视频文件放到nginx里面实现视频播放,但是把mp4文件放上去之后地址栏输入地址直接就是下载文件,这跟我想象的 ...
- 从零开始的微信小程序入门教程(二),初识WXML与WXSS
壹 ❀ 引 时隔大半年,我终于开始写小程序入门教程的第二篇了,其实我也在纳闷,这么久的时间我到底干了什么,仔细一想,我学了JavaScript部分进阶知识,学了ES6,系统性的去复习了angularj ...
- Python subProcess库以及Popen类的使用
subprocess库是一个十分强大且常用的库,它可以用来调用第三方工具(例如:exe.另一个python文件.命令行工具). 1.常用函数call() :执行由参数提供的命令,把数组作为参数运行命令 ...