OraclePreparedStatement的defaultBatchValue必须显式设置为100~500且autoCommit=false,否则executeUpdate()不攒批;需配合sendBatch()触发批量提交,禁用addBatch(),否则抛SQLException。
OraclePreparedStatement的defaultBatchValue必须显式设置
不设 defaultbatchvalue,executeupdate() 就不会攒批——哪怕你调了 100 次,jdbc 驱动仍按单条发,根本没触发 oracle 的原生批量机制。这是 oracle jdbc 特有的行为,和标准 jdbc addbatch/executebatch 完全不同,不能混用。
必须用 OracleConnection 和 OraclePreparedStatement,且在创建语句前就设好:
OracleConnection oc = (OracleConnection) connection;
oc.setDefaultExecuteBatch(100); // 关键:设为 100~500 之间较稳
OraclePreparedStatement ops = (OraclePreparedStatement) oc.prepareStatement(
"INSERT INTO t(a,b,c) VALUES(?,?,?)"
);
- 值设太小(如 10):触发频繁隐式提交,失去批量意义
- 值设太大(如 2000):可能触发 ORA-04030(PGA 内存不足),尤其字段多或含 BLOB
- 该值只对当前连接生效,连接池中每个新连接都得重设
defaultBatchValue生效的前提是禁用自动提交
defaultBatchValue 只在 autoCommit = false 时起作用。如果连接默认开启自动提交,每次 executeUpdate() 都会立刻 commit,batch 彻底失效。
常见错误写法:
connection.setAutoCommit(true); // ❌ 这行会让 defaultBatchValue 形同虚设 oc.setDefaultExecuteBatch(100); ops.executeUpdate(); // 实际仍是单条事务
- 必须在获取连接后第一时间调用
connection.setAutoCommit(false) - 别依赖连接池的“初始化 SQL”来设 autoCommit,Oracle JDBC 不认这个
- 事务最终必须显式
connection.commit(),否则连接归还池时可能卡住未提交事务
不能和标准 addBatch 混用,否则抛 SQLException
Oracle JDBC 明确禁止把 defaultBatchValue 和 addBatch() 放在同一段逻辑里。驱动检测到混合调用会直接 throw SQLException,报错信息类似 "Invalid operation for batch mode"。
以下写法是错的:
ops.addBatch(); // ❌ 禁止!用了 defaultBatchValue 就不能再碰 addBatch ops.executeUpdate(); ops.executeBatch(); // ❌ 更错,这行根本不会执行到
- 选 Oracle 模型就只用
executeUpdate()+sendBatch() - 选标准模型就只用
addBatch()+executeBatch(),并手动控制批次 - 两种模型底层协议不同,混用等于让驱动“左右互搏”
sendBatch() 是显式刷出批次的唯一方式
设了 defaultBatchValue 后,executeUpdate() 只是把语句缓存在客户端,真正发往数据库靠 sendBatch()。很多人漏掉这步,结果数据一直没进库。
正确流程:
for (int i = 0; i
-
sendBatch()返回 int[],和executeBatch()一样要检查是否全成功 - 若某次
sendBatch()失败,已缓存但未刷出的语句会丢失,需重做整批 - 别指望
close()或连接归还池能自动刷 batch,它不会
defaultBatchValue 是个“半自动”机制:它省了 addBatch 的循环,但把控制权交给了更隐蔽的 sendBatch 和更严格的上下文约束。最容易被忽略的是它和 autoCommit 的强绑定,以及与标准 batch 的互斥性——这两个点一旦踩错,性能不升反降。Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











