使用SqlInOutParameter调用Oracle存储过程在ojdbc8下触发断言异常
问题分析与解决方案
咱们直接揪出核心问题,这也是ojdbc8下测试断言失败的根源:
1. 错误用SqlInOutParameter声明纯IN参数
你的存储过程里INPUT_PARAM_1是纯IN参数,但代码里却用了SqlInOutParameter(这个类是给IN OUT类型参数用的)。这种错误在ojdbc6里因为驱动的宽松处理没暴露,但ojdbc8对参数校验更严格:
- 当
dsproxy的日志组件尝试读取这个被错误标记为IN OUT的参数的"输出值"时,由于存储过程根本没给它赋值,ojdbc8底层的NumberCommonAccessor会触发断言校验(检查数值长度是否为正),从而抛出AssertionError。 - 应用运行正常是因为默认JVM不开启断言(没有
-ea参数),断言错误会被直接忽略,但测试环境可能开启了断言,或者dsproxy的调用路径强制触发了这个校验。
2. 输出参数类型不匹配
你提供的存储过程示例中OUTPUT_PARAM_1是NUMBER类型,但代码里却用了OracleTypes.CURSOR声明,这会导致参数类型不匹配,后续也会引发其他异常。
修正后的代码
把参数声明改成正确的类型即可:
class CustomStoredProcedure extends org.springframework.jdbc.object.StoredProcedure { private static final String PROCEDURE_NAME = "MY_PROCEDURE"; private static final String INPUT_PARAM_1= "INPUT_PARAM_1"; public static final String OUTPUT_PARAM_1 = "OUTPUT_PARAM_1"; public CustomStoredProcedure (DataSource dataSource) { super(dataSource, PROCEDURE_NAME); // 纯IN参数用SqlParameter或SqlInParameter都可以 declareParameter(new SqlParameter(INPUT_PARAM_1, OracleTypes.NUMERIC)); // 匹配存储过程的NUMBER类型 declareParameter(new SqlOutParameter(OUTPUT_PARAM_1 , OracleTypes.NUMERIC)); compile(); } }
补充说明
SqlParameter和SqlInParameter都适用于纯IN参数,两者在Spring JDBC中的处理逻辑一致,选哪个都没问题。- 如果你的实际存储过程中
INPUT_PARAM_1确实是IN OUT类型(只是示例写错了),那必须确保存储过程内部对该参数进行了赋值,否则ojdbc8的断言校验还是会触发。 - 关于
dsproxy:它的OracleOutputParameterLogEntryCreator会遍历所有参数读取输出值,这也是为什么测试里会触发这个问题,而正常Spring JDBC调用不会主动读取纯IN参数的输出值。
内容的提问来源于stack exchange,提问作者Java Samurai
相关产品推荐
相关产品推荐

