Java批量数据库操作通过addBatch()复用PreparedStatement,参数化SQL仅参数变化,需开启批处理支持,分批addBatch()后executeBatch()执行并clearBatch()清空队列。

Java 中批量数据库操作通过 addBatch() 实现,核心是复用同一个 PreparedStatement,把多条参数化 SQL 的执行请求“攒起来”,再一次性提交给数据库,避免频繁网络往返和单条语句解析开销。
准备带参数的 PreparedStatement
必须使用 PreparedStatement(不能用 Statement),因为只有它支持参数绑定和批量操作。SQL 语句结构固定,仅参数变化:
String sql = "INSERT INTO user (name, age) VALUES (?, ?)"; PreparedStatement ps = conn.prepareStatement(sql);
- SQL 中用
?占位,后续用setXxx()设置每组参数 - 连接需开启批处理支持(大多数 JDBC 驱动默认支持,MySQL 需在 URL 加
&rewriteBatchedStatements=true才真正优化)
循环调用 addBatch() 添加批次
对每组数据,设置参数后调用 addBatch(),不立即执行:
for (User user : userList) {
ps.setString(1, user.getName());
ps.setInt(2, user.getAge());
ps.addBatch(); // 仅入队,不发送
}
- 每次
addBatch()把当前参数组合加入内部批处理队列 - 不会触发网络通信,也不校验 SQL 或参数合法性(错误可能在
executeBatch()时才抛出) - 建议控制单批数量(如 500–1000 条),避免内存溢出或事务过大
统一执行 executeBatch() 并处理结果
调用 executeBatch() 触发实际执行,返回每条语句影响的行数数组:
立即学习“Java免费学习笔记(深入)”;
int[] results = ps.executeBatch(); // results[i] 表示第 i 次 addBatch 对应语句影响的行数(通常为 1)
- 成功时返回
int[],每个元素对应一次addBatch()的影响行数 - 若某条失败,整个批次可能中断(取决于驱动和配置),可通过
executeBatch()抛出的BatchUpdateException获取部分成功结果(getUpdateCounts()) - 执行后需手动调用
clearBatch()清空队列(否则下次addBatch()会累加)
完整示例(含异常与资源管理)
结合 try-with-resources 和事务控制更健壮:
String sql = "INSERT INTO user (name, age) VALUES (?, ?)";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
conn.setAutoCommit(false); // 关闭自动提交
for (User user : userList) {
ps.setString(1, user.getName());
ps.setInt(2, user.getAge());
ps.addBatch();
// 每 500 条执行一次,防止内存占用过高
if (userList.indexOf(user) % 500 == 499) {
ps.executeBatch();
ps.clearBatch();
}
}
// 执行剩余
if (!userList.isEmpty() && userList.size() % 500 != 0) {
ps.executeBatch();
}
conn.commit();
} catch (SQLException e) {
conn.rollback();
throw e;
}
不复杂但容易忽略细节:预编译复用、参数绑定、分批提交、异常回滚、资源释放——这四步到位,批量插入效率可提升数倍甚至一个数量级。


















