Java批量插入需复用PreparedStatement,开启批量支持、关闭自动提交,循环addBatch后分批executeBatch并事务控制。

Java 中用 addBatch 和 executeBatch 批量插入数据,核心是复用同一个 PreparedStatement,把多条参数化的 SQL 操作攒成一批,再一次性提交,能显著减少数据库交互次数、提升插入性能。
准备支持批量操作的 PreparedStatement
必须在获取 Connection 时开启批量支持(部分 JDBC 驱动默认支持,但显式设置更稳妥):
- 使用
connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)(如需主键)或普通构造 - 确保数据库 URL 包含批量相关参数(例如 MySQL 加
&rewriteBatchedStatements=true可将多条 INSERT 合并为一条 multi-value 语句,大幅提升效率) - 关闭自动提交:
connection.setAutoCommit(false),便于手动控制事务
循环调用 addBatch 绑定并缓存参数
对每组待插入数据,设置参数后调用 addBatch(),不真正执行:
ps.setString(1, name); ps.setInt(2, age); ps.addBatch();- 不要在循环里反复
ps.clearParameters()——addBatch()内部已处理;但若跨批次重用同一 PreparedStatement,需在新批次开始前调用 - 建议每 1000 条左右调用一次
executeBatch()并清空(防内存溢出),再clearBatch()
执行 executeBatch 并处理结果
executeBatch() 返回 int[] 数组,每个元素对应对应一条语句影响的行数(成功为 >0,失败为 Statement.EXECUTE_FAILED):
立即学习“Java免费学习笔记(深入)”;
- 正常情况:检查返回值是否全为 1(单条 INSERT 影响行数通常为 1)
- 异常处理:捕获
BatchUpdateException,可通过e.getUpdateCounts()获取已执行成功的条目数,并决定是否回滚 - 事务提交:全部成功后调用
connection.commit();任一失败且需回滚,则connection.rollback()
完整示例片段(MySQL + try-with-resources)
注意:实际使用请替换为你的数据源和 SQL
String sql = "INSERT INTO user(name, age) VALUES (?, ?)";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
conn.setAutoCommit(false);
for (int i = 0; i < users.size(); i++) {
User u = users.get(i);
ps.setString(1, u.getName());
ps.setInt(2, u.getAge());
ps.addBatch();
// 每 1000 条执行一次
if ((i + 1) % 1000 == 0) {
int[] results = ps.executeBatch();
ps.clearBatch();
}
}
// 处理剩余不足 1000 条的数据
if (!users.isEmpty() && users.size() % 1000 != 0) {
ps.executeBatch();
}
conn.commit();
} catch (BatchUpdateException e) {
// 部分失败,可记录日志并回滚
System.err.println("批量插入异常,已执行 " + e.getUpdateCounts().length + " 条");
// ... rollback logic
} catch (SQLException e) {
// 其他 SQL 异常
}


















