一、循环插入

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批量插入的四种方式的更多相关文章

  1. mybatis中批量插入的两种方式(高效插入)

    MyBatis简介 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用 ...

  2. mybatis批量保存的两种方式(高效插入)

    知识点:mybatis中,批量保存的两种方式 1.使用mybatis foreach标签 2.mybatis ExecutorType.BATCH 参考博客:https://www.jb51.net/ ...

  3. CSS插入的四种方式

    一.什么是CSS CSS(Cascading style sheets  层叠样式表),CSS可以用以为网页构建样式表,通过样式表来达到对网页进行美化的效果.所谓层叠可以将网页想象成一层层的结构,高层 ...

  4. MyBatis_动态sql_foreach_mysql下foreach批量插入的两种方式

    方法1: 笔记要点出错分析与总结工程组织数据库组织0.重新修改Bean类    修改1.定义接口 //批量插入 public void addEmps(@Param("emps") ...

  5. mybatis批量更新的几种方式和性能对比

    https://blog.csdn.net/csdnbeyoung/article/details/106258611

  6. MyBatis 批量插入数据的 3 种方法!

    批量插入功能是我们日常工作中比较常见的业务功能之一,之前我也写过一篇关于<MyBatis Plus 批量数据插入功能,yyds!>的文章,但评论区的反馈不是很好,主要有两个问题:第一,对 ...

  7. C#批量插入数据到Sqlserver中的四种方式

    我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...

  8. C#_批量插入数据到Sqlserver中的四种方式

    先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...

  9. C#批量插入数据到Sqlserver中的四种方式 - 转

    先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...

  10. java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明)

    转载地址:http://www.devba.com/index.php/archives/4581.html java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明); ...

随机推荐

  1. 一些提供办公效率的软件(clover、f.lux、幕布),老赞了!

    1.clover 链接:http://cn.ejie.me/ Clover是由异次元的读者ejie团队开发的一款电脑窗口标签化工具.Clover是电脑中资源管理器的一个扩展程序,可以为其增加多标签页的 ...

  2. C/C++ 获取主机网卡MAC地址

    MAC地址(Media Access Control address),又称为物理地址或硬件地址,是网络适配器(网卡)在制造时被分配的全球唯一的48位地址.这个地址是数据链路层(OSI模型的第二层)的 ...

  3. 7.5 通过API判断进程状态

    进程状态的判断包括验证进程是否存在,实现方法是通过枚举系统内的所有进程信息,并将该进程名通过CharLowerBuff转换为小写,当转换为小写模式后则就可以通过使用strcmp函数对比,如果发现继承存 ...

  4. Windows Server ISO原版镜像文件下载(2023年04月)

    Windows Server 2022 (updated April 2023) (x64) - DVD (Chinese-Simplified) 链接:https://pan.baidu.com/s ...

  5. 图(树)的深度优先遍历dfs

    图的深度优先遍历 深度优先,即对于一个图或者树来说,在遍历时优先考虑图或者树的单一路径的深度.示意图如下 即深度优先搜索的核心就是对一个路径一直向下搜索,当搜索到头时就回溯到前一状态再寻找别的路 深搜 ...

  6. CF1010C Border 题解

    题目传送门 前置知识 最大公约数 | 裴蜀定理 简化题意 给定一个长度为 \(n\) 的序列 \(a\),求 \((\sum\limits_{i=1}^{n}d_ia_i) \bmod k\) 一共会 ...

  7. 从零开始的react入门教程(二),从react组件说到props/state的联系与区别

    壹 ❀ 引 在从零开始的react入门教程(一)一文中,我们搭建了第一个属于自己的react应用,并简单学习了jsx语法.jsx写法上与dom标签高度一致,当然我们也知道,本质上这些react元素都是 ...

  8. Ubuntu在无网络环境下,用离线源apt-get安装软件

    步骤概要如下: 1.假设目标安装的是服务器A,需先准备一台正常环境,且操作系统版本与A一致的服务器B: 2.用apt-get在服务器B上下载需要安装的包,并用dpkg-scanpackages依赖打包 ...

  9. Spring boot项目实战之记录应用访问日志

    1.说明 系统上线后往往我们需要知道都有哪些用户访问了应用的那些功能,以便更好的了解用户需求.防止恶意访问等.为此我们需要给应用添加记录访问日志的功能.下面就开始吧: 2.建表 CREATE TABL ...

  10. std::shared_ptr 线程安全方面的思考

    一直惦记着 std::shared_ptr 线程安全的问题,看了些文章后,又怕过段时间忘记了,遂记录下来 std::shared_ptr 的线程安全问题主要有以下两种: 引用计数的加减操作是否线程安全 ...