(场景题)怎么实现数据的批量插入?
批量插入大量数据(例如几十万条)时,如果每条单独插入,会非常慢,内存占用也高。这里总结一种 CSV → Java 对象 → MyBatis 批量插入 的通用实现方法。
1️⃣ 流程概览
准备 CSV 文件
CSV 文件每行表示一条数据
每列对应对象的一个字段
Java 读取 CSV
使用流式读取方式,逐行解析 CSV
每行生成一个 Java 对象
收集对象到列表
定义一个
batchList,每次把解析的对象加入列表当列表长度达到批量大小(如 1000 条)时执行批量插入
批量插入到数据库
使用 MyBatis
<foreach>或 JDBC 批处理批量插入完成后,清空列表,继续下一批
处理剩余数据
CSV 读完后,如果
batchList还有未满的对象,也要插入一次
2️⃣ Java 读取 CSV 示例
使用 OpenCSV 流式读取:
int batchSize = 1000;
List<MyData> batchList = new ArrayList<>();try (CSVReader reader = new CSVReader(new FileReader("data.csv"))) {String[] row;while ((row = reader.readNext()) != null) {MyData record = new MyData();record.setField1(row[0].trim());record.setField2(row[1].trim());// …设置其他字段…batchList.add(record);if (batchList.size() == batchSize) {myMapper.insertBatch(batchList); // MyBatis批量插入batchList.clear(); // 清空列表}}if (!batchList.isEmpty()) {myMapper.insertBatch(batchList);}
} catch (IOException e) {e.printStackTrace();
}
✅ 特点:
流式处理:不会一次性占用大量内存
分批控制:每批插入数据库,提升性能
3️⃣ MyBatis 批量插入 SQL 示例
<insert id="insertBatch" parameterType="java.util.List">INSERT INTO my_table (field1, field2, field3)VALUES<foreach collection="list" item="item" separator=",">(#{item.field1}, #{item.field2}, #{item.field3})</foreach>
</insert>
解释:
parameterType="java.util.List":告诉 MyBatis 参数是一个列表<foreach>遍历列表,每个元素用item访问separator=",":每条记录之间用逗号分隔,生成完整 SQL
注意:SQL 太长可能会超出数据库限制,所以建议 每批 500~1000 条
4️⃣ 原理解析
MyBatis 将
List中每个对象的字段替换到#{item.xxx}占位符<foreach>拼接成一条完整的INSERT ... VALUES (...),(...),(...)SQL数据库一次执行这条 SQL,即可插入多条记录
相比逐条插入,性能提升显著,因为减少了网络往返和事务提交次数
5️⃣ 优化建议
批次大小:500~1000 条比较稳,太大可能导致 SQL 超长
内存管理:使用流式读取 CSV,不要一次性把所有数据读入内存
事务控制:每批单独提交,方便回滚
大数据量:超过几十万条,建议使用 JDBC 批处理(ExecutorType.BATCH)
6️⃣ 总结
MyBatis 批量插入的核心就是 把 CSV 转成 Java 对象 → 收集成批 →
<foreach>拼 SQL → 一次性插入数据库好处:
显著减少数据库交互次数
控制内存占用
易于维护和调试
