Oracle ARRAY不能直接映射Java原生数组,因JDBC仅识别数据字典注册的SQL类型(CREATE TYPE定义),不支持PL/SQL内部类型;需用oracle.sql.ARRAY中转,注意类型注册、驱动版本、大小写匹配及array.free()资源释放。
oracle 的 array 类型不能直接映射为 java 原生数组,必须通过 jdbc 的 oracle.sql.array 类型中转,且需提前在数据库中定义 sql 类型(不是 pl/sql 类型)。
为什么 ARRAY 传不进 Java?常见报错是 ORA-00902: invalid datatype 或 java.sql.SQLException: Invalid column type
根本原因是:JDBC 驱动只识别 Oracle 数据字典里注册的 SQL 类型(即用 CREATE TYPE ... AS TABLE OF ... 创建的类型),不识别存储过程内部声明的 PL/SQL 类型(如 TYPE my_tab IS TABLE OF NUMBER)。如果你在包里定义了类型但没在 SQL 层注册,CallableStatement.registerOutParameter(idx, Types.ARRAY) 就会失败。
- 检查类型是否可查:
SELECT * FROM ALL_TYPES WHERE TYPE_NAME = 'YOUR_ARRAY_TYPE_NAME' - 确保类型是
SQL类型:创建语句必须是CREATE OR REPLACE TYPE my_num_array AS TABLE OF NUMBER,不能带INDEX BY或在包体内定义 - 驱动版本要匹配:Oracle 12c+ 推荐用
ojdbc8.jar,旧驱动对ARRAY支持不完整
Java 端如何正确获取 oracle.sql.ARRAY 并转成 Java 数组
拿到 ARRAY 后不能直接调 toString() 或强转,得用 getArray() 或 toJdbcArray();返回值类型取决于 SQL 类型元素,比如 NUMBER → BigDecimal[],VARCHAR2 → String[]。
- 推荐写法:
Object[] javaArr = (Object[]) oraArray.getArray()(最通用) - 若确定是数值类型,可转:
BigDecimal[] bdArr = (BigDecimal[]) oraArray.getArray() - 避免用
oraArray.toJdbcArray():它返回的是Object,类型擦除后容易 ClassCastException - 注意空值:
getArray()对 NULL 元素返回null,不是BigDecimal.ZERO
Java 往 Oracle 存储过程传入 ARRAY 参数
必须用 Connection.createArrayOf()(JDBC 4.2+)或 new ARRAY(...) 构造器(老方式),不能用 setObject(idx, new String[]{"a","b"})。
- JDBC 4.2+ 推荐(简洁安全):
Array sqlArray = conn.createArrayOf("MY_STR_ARRAY", new String[]{"x","y"}); cs.setArray(1, sqlArray); - 老方式(需 oracle.jdbc.OracleConnection):
OracleConnection oc = conn.unwrap(OracleConnection.class); ARRAY arr = new ARRAY(descriptor, oc, new String[]{"x","y"}); - 类型名大小写敏感:传入的类型名必须和
ALL_TYPES.TYPE_NAME完全一致(通常是大写) - 元素类型要匹配:Java 数组元素类型必须能被 Oracle 隐式转为目标 SQL 类型的元素,比如
String[]对应VARCHAR2,Integer[]对应NUMBER
性能与资源清理要注意什么
oracle.sql.ARRAY 是 JDBC 资源对象,底层持有数据库连接句柄,不显式释放可能引发连接泄漏或内存堆积。
立即学习“Java免费学习笔记(深入)”;
- 务必在
finally或 try-with-resources 中调用array.free()(JDBC 4.2+) - 不要长期缓存
ARRAY实例:它绑定到特定连接,连接关闭后失效 - 大数据量慎用:Oracle 数组在传输时会序列化为 RAW,超过几万条易触发
ORA-04030(内存不足) - 替代方案考虑:超大集合建议改用临时表 + 表关联,比
ARRAY更稳定
最常被忽略的是类型注册这一步——开发时在 SQL Developer 里测试成功,上线后却报 invalid datatype,大概率是生产库没执行 CREATE TYPE,或者用了同义词但没授权给应用用户。别信“类型看起来一样”,查 ALL_TYPES 才算数。


















