Java批量插入应使用PreparedStatement批处理而非手动拼接SQL,因其可防止SQL注入、自动处理转义与null、避免语法错误,并配合rewriteBatchedStatements=true等配置提升性能。

Java 中批量插入数据不建议手动拼接 SQL 字符串,尤其涉及用户输入时极易引发 SQL 注入、类型转换错误、引号转义混乱等问题。真正安全高效的做法是使用预编译参数(PreparedStatement)配合 addBatch() / executeBatch(),或借助 MyBatis、JDBC 批处理配置等成熟方案。
为什么不要手动拼接 INSERT SQL?
手动拼接(如 "INSERT INTO user(name,age) VALUES ('"+name+"',"+age+")")存在严重隐患:
- 遇到名字含单引号(如
O'Connor)会直接导致 SQL 语法错误 - 数值字段若为空或非数字,运行时报
NumberFormatException - 无法防止 SQL 注入——恶意输入可闭合引号并追加任意语句
- 字符串需要手动转义、日期需格式化、NULL 值难统一处理
- 大量字符串拼接性能差,还容易因括号/逗号位置出错
推荐做法:用 PreparedStatement 批处理
这是 JDBC 原生、安全、通用的批量插入方式:
String sql = "INSERT INTO user(name, age, email) VALUES (?, ?, ?)";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
for (User user : userList) {
ps.setString(1, user.getName()); // 自动处理 null 和转义
ps.setInt(2, user.getAge());
ps.setString(3, user.getEmail());
ps.addBatch(); // 加入批次,不立即执行
}
int[] results = ps.executeBatch(); // 一次性提交所有
System.out.println("成功插入 " + results.length + " 条");
}
提升性能的关键配置
仅用 addBatch() 不够,还需数据库和 JDBC 驱动配合:
- MySQL 连接 URL 加上
rewriteBatchedStatements=true(如jdbc:mysql://localhost:3306/db?rewriteBatchedStatements=true),让驱动把多条INSERT合并为INSERT INTO t VALUES(...),(...),(...)形式 - 调用
ps.executeBatch()前,可设conn.setAutoCommit(false),最后conn.commit(),减少事务开销 - 每批控制在 500–2000 条(避免内存溢出或锁表太久),大列表记得分批处理
框架场景:MyBatis 批量插入
若用 MyBatis,推荐 foreach 标签生成多值 INSERT(MySQL 支持):
<insert id="batchInsert">
INSERT INTO user(name, age, email) VALUES
<foreach collection="list" item="u" separator=",">
(#{u.name}, #{u.age}, #{u.email})
</foreach></insert>
注意:该写法依赖数据库是否支持多值插入(MySQL ✅,PostgreSQL 需 9.5+,Oracle ❌)。对不支持的库,MyBatis Plus 的 saveBatch() 或自定义分批循环仍是更稳妥选择。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











