You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用含VARRAY对象的Oracle存储过程时遇ORA-06550/PLS-00306错误(MyBatis)

MyBatis调用Oracle存储过程(含VARRAY参数)的ORA-06550/PLS-00306错误排查

核心错误原因

ORA-06550与PLS-00306本质是参数绑定不匹配,在涉及Oracle自定义VARRAY类型时,大概率是MyBatis未正确识别集合类型的映射规则,而非参数名称/顺序问题。

逐步排查与修复方案

1. 注册VARRAY类型处理器

Oracle的VARRAY属于自定义集合类型,MyBatis无法自动映射,必须显式实现并注册类型处理器:

  • 编写类型处理器(继承BaseTypeHandler):
    public class OracleVarrayTypeHandler extends BaseTypeHandler<List<String>> {
        // 替换为你的VARRAY完整类型名(含schema)
        private static final String VARRAY_FULL_NAME = "SCOTT.STRING_VARRAY";
    
        @Override
        public void setNonNullParameter(PreparedStatement ps, int idx, List<String> param, JdbcType jdbcType) throws SQLException {
            Connection conn = ps.getConnection();
            // 按Oracle类型创建数组
            Array oracleArray = conn.createArrayOf(VARRAY_FULL_NAME, param.toArray());
            ps.setArray(idx, oracleArray);
        }
    
        @Override
        public List<String> getNullableResult(ResultSet rs, String colName) throws SQLException {
            return parseOracleArray(rs.getArray(colName));
        }
    
        @Override
        public List<String> getNullableResult(ResultSet rs, int colIdx) throws SQLException {
            return parseOracleArray(rs.getArray(colIdx));
        }
    
        @Override
        public List<String> getNullableResult(CallableStatement cs, int paramIdx) throws SQLException {
            return parseOracleArray(cs.getArray(paramIdx));
        }
    
        // 解析Oracle Array为Java List
        private List<String> parseOracleArray(Array array) throws SQLException {
            if (array == null) return null;
            Object[] elements = (Object[]) array.getArray();
            return Arrays.asList(Arrays.copyOf(elements, elements.length, String[].class));
        }
    }
    
  • 在MyBatis配置文件中注册处理器:
    <configuration>
        <typeHandlers>
            <typeHandler handler="com.yourpackage.OracleVarrayTypeHandler" 
                        javaType="java.util.List" 
                        jdbcType="ARRAY"/>
        </typeHandlers>
    </configuration>
    

2. 修正MyBatis映射文件参数配置

确保OUT参数的mode、jdbcType、typeHandler配置完整:

<select id="callVarrayProc" statementType="CALLABLE">
    {call SCOTT.PROC_WITH_VARRAY(
        #{inputParam, mode=IN, jdbcType=VARCHAR},
        #{outputVarray, mode=OUT, jdbcType=ARRAY, typeHandler=com.yourpackage.OracleVarrayTypeHandler},
        #{outputCode, mode=OUT, jdbcType=NUMBER}
    )}
</select>

注意:必须指定VARRAY的完整Oracle类型名(含schema),否则数据库无法定位类型。

3. 验证Java与Oracle类型匹配

  • 若Oracle VARRAY定义为VARRAY(100) OF VARCHAR2(50),Java端用List<String>接收即可;
  • 若VARRAY是自定义OBJECT类型的集合,需为OBJECT创建对应Java实体类,并在类型处理器中实现实体与Oracle OBJECT的转换逻辑。

4. 排除存储过程本身问题

先在数据库端直接调用存储过程,确认过程本身无错:

DECLARE
    v_input VARCHAR2(50) := 'test';
    v_varray SCOTT.STRING_VARRAY;
    v_code NUMBER;
BEGIN
    SCOTT.PROC_WITH_VARRAY(v_input, v_varray, v_code);
    DBMS_OUTPUT.PUT_LINE('输出码:' || v_code);
    -- 遍历VARRAY验证结果
    FOR i IN 1..v_varray.COUNT LOOP
        DBMS_OUTPUT.PUT_LINE('元素' || i || ':' || v_varray(i));
    END LOOP;
END;
/

如果数据库端调用报错,优先修复存储过程定义;如果正常,问题必然在MyBatis的映射配置上。

5. 检查参数绑定细节

  • Oracle存储过程对参数名称大小写敏感,确保MyBatis中@Param注解的名称与存储过程参数名完全一致;
  • 若名称绑定仍有问题,可尝试改用位置绑定(MyBatis支持#{}按位置索引绑定,但需注意参数顺序)。

高频错误点总结

  • 未注册VARRAY类型处理器,MyBatis无法解析Oracle集合类型;
  • 映射文件中OUT参数未指定jdbcType=ARRAY或typeHandler路径错误;
  • VARRAY类型名未带schema,数据库找不到自定义类型;
  • Java接收类型与VARRAY元素类型不匹配(如Oracle用NUMBER,Java用String)。

内容的提问来源于stack exchange,提问作者Emmanuele Guerriero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 05:05:38