升级Oracle JDBC驱动后Spring StoredProcedure调用报ORA-06550错误的参数定义修正方案咨询
遇到这种驱动升级后突然“掉链子”的情况真的闹心!我帮你梳理下核心问题和可行的修复方向:
核心问题定位
从报错日志和你的代码来看,参数数量不匹配是触发PLS-00306错误的直接原因:
- 日志里显示调用的存储过程
MASTERDATA.GETACCOUNTFROMIBAN有19个参数(1个输入+14个输出+4个额外输入),但你的GetAccountFromIbanProcedure只声明了15个参数(1个输入+14个输出),完全没处理第16-19位的输入参数。 - 旧版本Oracle JDBC可能对这种参数缺失的情况有兼容性容错,但23.7.0版本严格校验了参数数量与存储过程定义的一致性,直接抛出了错误。
另外,你使用VARCHAR.getVendorTypeNumber()这类Oracle专属类型编号的方式,也可能因为新驱动的类型映射调整出现隐性问题。
具体修复步骤
补全缺失的输入参数声明
在afterPropertiesSet()方法里,把日志中显示的第16-19位输入参数补充进去,要严格对应存储过程定义的类型:@Override public void afterPropertiesSet() { // 现有参数声明保持不变 declareParameter(new SqlParameter("iban", Types.VARCHAR)); declareParameter(new SqlOutParameter("returnCode", Types.VARCHAR)); declareParameter(new SqlOutParameter("msgCode", Types.VARCHAR)); // ... 其他12个输出参数声明 declareParameter(new SqlOutParameter("failbackLapse", Types.DECIMAL)); // 新增缺失的4个输入参数,类型根据存储过程实际定义调整 declareParameter(new SqlParameter("paramFlag1", Types.BOOLEAN)); // 对应第16位的false declareParameter(new SqlParameter("paramInt", Types.INTEGER)); // 对应第17位的1 declareParameter(new SqlParameter("paramFlag2", Types.BOOLEAN)); // 对应第18位的true declareParameter(new SqlParameter("paramFlag3", Types.BOOLEAN)); // 对应第19位的false // 别忘了调用super.afterPropertiesSet()完成初始化 super.afterPropertiesSet(); }注意参数名要和你调用存储过程时传入的
Map键值对应,类型要和存储过程的参数定义完全匹配。替换Oracle专属类型编号为标准JDBC类型
放弃使用VARCHAR.getVendorTypeNumber()、DECIMAL.getVendorTypeNumber()这类Oracle私有类型常量,改用java.sql.Types下的标准常量,避免驱动版本变化带来的映射冲突:// 错误写法 // declareParameter(new SqlParameter("iban", VARCHAR.getVendorTypeNumber())); // 正确写法 declareParameter(new SqlParameter("iban", Types.VARCHAR));严格核对参数顺序与存储过程定义
Oracle存储过程对参数顺序是强敏感的,哪怕参数名称正确,顺序不符也会触发类型/数量错误。请对照数据库中MASTERDATA.GETACCOUNTFROMIBAN的定义,确保你声明参数的顺序和存储过程的参数列表完全一致。快速验证小技巧
如果不确定问题是否出在StoredProcedure的封装上,可以先用JdbcTemplate直接调用CallableStatement做小范围测试:jdbcTemplate.execute(connection -> { CallableStatement cs = connection.prepareCall("{call MASTERDATA.GETACCOUNTFROMIBAN(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}"); // 设置第1位输入参数 cs.setString(1, "测试IBAN"); // 注册所有输出参数 cs.registerOutParameter(2, Types.VARCHAR); cs.registerOutParameter(3, Types.VARCHAR); // ... 依次注册第4到15位的输出参数 // 设置第16-19位输入参数 cs.setBoolean(16, false); cs.setInt(17, 1); cs.setBoolean(18, true); cs.setBoolean(19, false); // 执行调用 cs.execute(); // 打印输出参数验证结果 System.out.println("returnCode: " + cs.getString(2)); return null; });如果这段代码能成功执行,说明问题确实出在StoredProcedure的参数声明上,按前面的步骤调整即可。
总结
旧驱动的兼容性容错掩盖了参数声明不全的问题,新驱动的严格校验让这个问题暴露了出来。补全缺失的参数+改用标准JDBC类型,基本就能解决这个报错。
内容来源于stack exchange

