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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:57:25