升级ojdbc11后批量插入自增ID表报autoKeyInfo未初始化错误
问题根因
抛出java.lang.AssertionError: autoKeyInfo is not initialized是ojdbc11 21.6.0.0.1版本的驱动层原生缺陷:该版本驱动在处理批量插入+需要返回数据库生成主键的场景时,内部autoKeyInfo字段的初始化逻辑存在分支遗漏。当调用prepareStatement时传入Statement.RETURN_GENERATED_KEYS标识、再调用executeBatch()执行批量操作时,就会直接触发该断言错误,和上层使用的ORM框架(Spring Data JDBC、MyBatis等)没有关系。
可行解决方案
按优先级从高到低排列:
- 更换无缺陷的JDBC驱动版本:这是最彻底的解决方式。你可以选择回退到之前使用的ojdbc8 19.6.0.0版本,也可以选择升级到ojdbc11 21.7.0.0及以上的正式版本——Oracle在21.7版本中正式修复了该初始化逻辑bug;如果需要停留在19c大版本的驱动,ojdbc11 19.13.0.0.1也是经过验证无该问题的稳定版本。注意避开ojdbc11 21.5.0.0、21.6.0.0两个大版本,这两个版本除了该问题外,还存在批量插入参数错位、时间类型转换错误等多个已知缺陷。
- 代码层面临时规避:如果暂时无法更换驱动版本,可以调整JDBC语句创建逻辑,绕过触发bug的代码分支。不要在创建
PreparedStatement时直接传入Statement.RETURN_GENERATED_KEYS参数,改为显式传入需要返回的主键列名数组或列索引数组,示例写法:
这种写法不会触发驱动的缺陷分支,可以正常执行批量插入并返回生成的主键值。// 原触发bug的写法 // PreparedStatement ps = connection.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS); // 替换为显式指定主键列的写法,假设主键列名为ID PreparedStatement ps = connection.prepareStatement(insertSql, new String[]{"ID"}); - 框架配置应急方案:如果是通过上层ORM框架操作数据库、且不方便修改JDBC原生逻辑,可以暂时关闭批量插入时的自动主键回填能力,插入完成后单独查询生成的主键值即可。该方案会损失部分批量插入性能,仅适合短期应急使用。
内容的提问来源于stack exchange,提问作者Jens Schauder
相关产品推荐
相关产品推荐

