Oracle JDBC执行rs.next()抛出ArrayIndexOutOfBoundsException求助
Oracle 11.2 查询ALL_OBJECTS时ResultSet.next()抛出ArrayIndexOutOfBoundsException 解决方法
问题背景
- 环境:Oracle 11.2,Spring Boot 2.3.12,使用BasicDataSource连接池
- 症状:执行查询ALL_OBJECTS的SQL时,每次调用
rs.next()都会抛出ArrayIndexOutOfBoundsException,堆栈指向Oracle驱动的T4CTTIrxdsBitset.set方法 - 已尝试:更换ojdbc8-12.2.0.1、ojdbc6-11.2.0.3、ojdbc8-19等驱动版本,设置
Statement.setFetchSize(),均未解决问题
核心原因
该错误本质是Oracle驱动与数据库版本不兼容导致的解析异常:高版本驱动(如ojdbc8、ojdbc19)针对Oracle 12c+的特性做了逻辑优化,连接低版本Oracle 11.2时,处理结果集的位向量(BitVector)解析会出现索引越界;加上ALL_OBJECTS是包含大量字段的系统视图,驱动解析全量字段时更容易触发该bug。
解决方案
1. 严格匹配驱动与Oracle版本
Oracle 11.2必须使用对应版本的稳定驱动,推荐使用ojdbc6-11.2.0.4.jar(官方适配11.2的最优版本),禁止使用适配12c+的ojdbc8或19c+的ojdbc19。
2. 避免SELECT *,明确指定所需字段
ALL_OBJECTS包含数十个字段,SELECT *会让驱动处理大量不必要的元数据,大幅增加触发bug的概率。修改SQL为仅查询业务需要的字段:
String sql = "SELECT OWNER, OBJECT_NAME, OBJECT_TYPE, LAST_DDL_TIME FROM ALL_OBJECTS O WHERE O.OWNER = 'LINEWELL' AND O.OBJECT_TYPE IN ('TABLE', 'VIEW')";
3. 指定结果集类型为向前只读
默认创建的Statement可能生成可滚动结果集(InsensitiveScrollableResultset),其复杂的处理逻辑更容易触发异常。创建Statement时显式指定结果集类型:
Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
4. 优化连接池与驱动配置
在BasicDataSource中添加驱动属性,优化结果集读取逻辑:
datasource.addConnectionProperty("oracle.jdbc.defaultRowPrefetch", "100"); datasource.addConnectionProperty("oracle.jdbc.useFetchSizeWithLongColumn", "true");
修改后的完整代码示例
public void demo() { List<Map<String, String>> resultList = new ArrayList<>(); // 仅查询所需字段 String sql = "SELECT OWNER, OBJECT_NAME, OBJECT_TYPE, LAST_DDL_TIME FROM ALL_OBJECTS O WHERE O.OWNER = 'LINEWELL' AND O.OBJECT_TYPE IN ('TABLE', 'VIEW')"; BasicDataSource datasource; // 已初始化的数据源 try ( Connection con = datasource.getConnection(); // 指定向前只读的结果集类型 Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); ResultSet rs = stmt.executeQuery(sql) ) { stmt.setFetchSize(100); // 设置合理的批量读取大小 while (rs.next()) { Map<String, String> map = new HashMap<>(); map.put("TableCatalog", rs.getString("OWNER")); map.put("TableSchema", rs.getString("OWNER")); map.put("TableName", rs.getString("OBJECT_NAME")); map.put("TableType", rs.getString("OBJECT_TYPE")); map.put("LastModifyTime", rs.getString("LAST_DDL_TIME")); resultList.add(map); } } catch (Exception e) { e.printStackTrace(); } System.out.println(resultList.size()); }
额外排查方向
如果上述方法无效,可尝试:
- 升级Spring Boot 2.3.x到最新补丁版本,或升级到2.4+(注意兼容性)
- 检查Oracle 11.2是否安装了最新CPU补丁,部分旧版本存在驱动交互bug
内容的提问来源于stack exchange,提问作者great-jin
相关产品推荐
相关产品推荐

