使用MyBatis TypeHandler映射List<Dep>到Oracle数组时遇ORA-06550错误求助
排查MyBatis TypeHandler映射Oracle数组时的ORA-06550/PLS-00103错误
我之前也踩过Oracle数组映射的坑,结合你给出的代码片段,咱们来一步步拆解这个问题:
可能的错误原因
- 数据库类型与代码定义不匹配:你注释掉的
StructDescriptor.createDescriptor("MEMS_ARR", connection)里的类型名,可能和Oracle数据库中实际定义的数组/结构体类型不一致(Oracle默认大小写敏感,注意要完全匹配)。 - 数组创建逻辑缺失:从截断的代码看,你只初始化了
Struct[] structs但没有正确填充结构体,也没有创建Oracle原生的ARRAY对象,直接传递Struct数组会让Oracle无法识别参数类型。 - 未使用Oracle JDBC扩展:标准JDBC Connection没有创建Oracle数组的方法,必须强转为OracleConnection才能调用专属API。
- 代码语法错误:你代码里的
parameter.si...明显是截断了,实际如果是拼写错误(比如少写ze),会导致参数长度计算错误,间接引发Oracle的参数解析异常。
解决办法
1. 先确认Oracle端的类型定义
必须先在数据库中定义对应的结构体和数组类型,比如:
-- 先定义对应Dep类的结构体类型 CREATE OR REPLACE TYPE DEP_TYPE AS OBJECT ( dep_id NUMBER, dep_name VARCHAR2(100) ); -- 再定义该结构体的数组类型 CREATE OR REPLACE TYPE MEMS_ARR AS TABLE OF DEP_TYPE;
确保代码里引用的类型名和这里的完全一致(比如MEMS_ARR、DEP_TYPE都是大写)。
2. 修正TypeHandler的setParameter方法
补全逻辑并使用Oracle JDBC扩展API:
@Override public void setParameter(PreparedStatement ps, int i, List<Dep> parameter, JdbcType jdbcType) throws SQLException { // 处理空参数的情况 if (parameter == null || parameter.isEmpty()) { ps.setNull(i, Types.ARRAY, "MEMS_ARR"); return; } // 强转为OracleConnection,调用专属API OracleConnection oracleConn = ps.getConnection().unwrap(OracleConnection.class); // 构建Struct数组(对应DEP_TYPE结构体) StructDescriptor structDesc = StructDescriptor.createDescriptor("DEP_TYPE", oracleConn); Struct[] structs = new Struct[parameter.size()]; for (int idx = 0; idx < parameter.size(); idx++) { Dep dep = parameter.get(idx); // 按结构体属性顺序封装数据 Object[] attributes = new Object[]{dep.getDepId(), dep.getDepName()}; structs[idx] = new STRUCT(structDesc, oracleConn, attributes); } // 创建Oracle数组并设置到PreparedStatement ARRAY oracleArray = oracleConn.createARRAY("MEMS_ARR", structs); ps.setArray(i, oracleArray); }
3. 检查MyBatis的Mapper配置
在XML或注解中明确指定参数的jdbcType和typeHandler:
XML方式:
<insert id="batchInsertDeps" parameterType="java.util.List"> INSERT INTO your_table (dep_list_col) VALUES (#{depList, jdbcType=ARRAY, typeHandler=com.your.package.DepListTypeHandler}) </insert>
注解方式:
@Insert("INSERT INTO your_table (dep_list_col) VALUES (#{depList, jdbcType=ARRAY, typeHandler=com.your.package.DepListTypeHandler})") void batchInsertDeps(@Param("depList") List<Dep> depList);
4. 修复代码语法问题
确保你实际代码里的parameter.si...是完整的parameter.size(),避免因语法错误导致参数传递异常。
内容的提问来源于stack exchange,提问作者osama yaccoub




