总结
到这里大家应该都清楚的知道了 mybatis-plus 的批量插入虽然是遍历插入,但是不是一个insert就一次io,而是多条insert打包在一起分批发送的,所以性能不会有什么太大问题。不过笔者这里不是鼓吹大家都用这个批量插入就好了,实际工作中会有更多要求,其实这个简单的批量插入是没法满足的。因此,笔者只是提倡可以根据自己工作实际情况决定,但是性能方面就不用太过担心,mybatis-plus也有考虑的,详情请看:通用 insertBatch 为什么放在 service 层处理
扩展
如果使用 mybatis-plus 3.4+ 版本,并且连接的是 MySQL 8.0 或更高版本的数据库,那么 mybatis-plus 将会自动利用 MySQL 8.0 的原生批量插入功能来执行批量插入操作。
具体实现的关键是在 mybatis-plus 的底层使用了 JDBC 的 addBatch 和 executeBatch 方法。当调用 mybatis-plus 的批量新增时,mybatis-plus 会将待插入的对象列表传递给底层的 JDBC 驱动程序。而 MySQL 8.0 的 JDBC 驱动程序会自动将这些插入语句封装成批量插入的 SQL 语句,并一次性发送给数据库执行。
需要注意的是,要确保以下条件满足才能利用 MySQL 8.0 的批量插入功能:
- 使用 MySQL 8.0 或更高版本的数据库
- 使用兼容 MySQL 8.0 的 JDBC 驱动程序(如 mysql-connector-java 版本 8.0 或更高)
- 使用 mybatis-plus 3.4+ 版本
//jdbcde 批量插入 public void importData() { //结果集中数据为0时,结束方法.进行下一次调用 if (employeeList.size() == 0) { return; } //JDBC分批插入+事务操作完成对20w数据的插入 Connection conn = null; PreparedStatement ps = null; try { long startTime = System.currentTimeMillis(); System.out.println(employeeList.size() + "条,开始导入到数据库时间:" + startTime + "ms"); conn = dataSource.getConnection(); //控制事务:默认不提交 conn.setAutoCommit(false); String sql = "insert into employee (`employee_id`, `employee_name`, `age`, `gender`, `create_time`) values"; sql += "(?,?,?,?,?,?)"; ps = conn.prepareStatement(sql); //循环结果集:这里循环不支持lambda表达式 for (int i = 0; i < employeeList.size(); i++) { EmployeeDO item = employeeList.get(i); ps.setLong(1, item.getEmployeeId()); ps.setString(2, item.getEmployeeName()); ps.setInt(3, item.getAge()); ps.setString(4, item.getGender()); ps.setDate(5, item.getCreateTime()); //将一组参数添加到此 PreparedStatement 对象的批处理命令中。 ps.addBatch(); } //执行批处理 ps.executeBatch(); //手动提交事务 conn.commit(); long endTime = System.currentTimeMillis(); System.out.println(employeeList.size() + "条,结束导入到数据库时间:" + endTime + "ms"); System.out.println(employeeList.size() + "条,导入用时:" + (endTime - startTime) + "ms"); } catch (Exception e) { e.printStackTrace(); } finally { //关连接 try { ps.close(); } catch (SQLException e) { throw new RuntimeException(e); } try { conn.close(); } catch (SQLException e) { throw new RuntimeException(e); } } }
待续..