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

如何通过Spring的SimpleJdbcCall获取Oracle存储过程返回值

解决SimpleJdbcCall调用Oracle存储过程获取返回值的问题

首先得明确一个关键知识点:Oracle的存储过程(PROCEDURE)不能用return语句返回值,只有函数(FUNCTION)才支持用return返回结果。你之前用return无效就是这个原因,存储过程要返回数据必须通过OUT参数来实现。下面给你分步讲解解决方案:

一、先确认Oracle存储过程的正确定义

首先要确保你的存储过程已经定义了OUT参数,比如下面这个示例(可根据你的业务调整参数):

CREATE OR REPLACE PACKAGE NAMED_DRIVER_SAVE AS
    PROCEDURE PROC_SAVE_NAMED_DRIVER(
        -- 输入参数,对应QuotationDO的业务字段
        p_quotation_id IN NUMBER,
        p_driver_name IN VARCHAR2,
        -- 输出参数,用于返回执行结果
        p_return_msg OUT VARCHAR2,
        p_return_code OUT NUMBER
    );
END NAMED_DRIVER_SAVE;

CREATE OR REPLACE PACKAGE BODY NAMED_DRIVER_SAVE AS
    PROCEDURE PROC_SAVE_NAMED_DRIVER(
        p_quotation_id IN NUMBER,
        p_driver_name IN VARCHAR2,
        p_return_msg OUT VARCHAR2,
        p_return_code OUT NUMBER
    ) AS
    BEGIN
        -- 执行数据保存逻辑
        INSERT INTO NAMED_DRIVERS(QUOTATION_ID, DRIVER_NAME) 
        VALUES(p_quotation_id, p_driver_name);
        
        -- 设置成功返回值
        p_return_msg := '数据保存成功';
        p_return_code := 0;
        
        COMMIT;
    EXCEPTION
        WHEN OTHERS THEN
            -- 异常时返回错误信息
            p_return_msg := '保存失败:' || SQLERRM;
            p_return_code := -1;
            ROLLBACK;
    END PROC_SAVE_NAMED_DRIVER;
END NAMED_DRIVER_SAVE;

二、修改Java代码,用SimpleJdbcCall获取OUT参数

接下来调整你的Java代码,通过declareParameters声明OUT参数,执行后从返回的Map中取出结果:

public void saveNamedDrivers(QuotationDO quotationDO) {
    try {
        System.out.println(" 11111");
        SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(dataSource)
                .withCatalogName("NAMED_DRIVER_SAVE") // 指定存储过程所在的包名
                .withProcedureName("PROC_SAVE_NAMED_DRIVER") // 指定存储过程名
                // 声明参数:IN参数用SqlParameter,OUT参数用SqlOutParameter
                .declareParameters(
                        new SqlParameter("p_quotation_id", Types.NUMERIC),
                        new SqlParameter("p_driver_name", Types.VARCHAR),
                        new SqlOutParameter("p_return_msg", Types.VARCHAR),
                        new SqlOutParameter("p_return_code", Types.NUMERIC)
                );

        // 构建输入参数Map,key要和存储过程的参数名严格匹配(Oracle默认大写,注意大小写一致)
        Map<String, Object> inParams = new HashMap<>();
        inParams.put("p_quotation_id", quotationDO.getQuotationId());
        inParams.put("p_driver_name", quotationDO.getDriverName());

        // 执行存储过程,返回包含OUT参数的Map
        Map<String, Object> resultMap = simpleJdbcCall.execute(inParams);

        // 从结果Map中取出返回值
        String returnMsg = (String) resultMap.get("p_return_msg");
        Integer returnCode = (Integer) resultMap.get("p_return_code");

        // 根据返回值做后续处理,比如日志记录或异常抛出
        System.out.println("存储过程返回:code=" + returnCode + ", msg=" + returnMsg);
        if (returnCode != 0) {
            throw new RuntimeException("保存命名司机失败:" + returnMsg);
        }

    } catch (Exception e) {
        e.printStackTrace();
        // 统一异常处理逻辑
    }
}

三、额外说明:如果用Oracle函数(FUNCTION)的情况

如果你更倾向于用return返回结果,那应该把存储过程改成函数(FUNCTION),对应的Java调用方式如下:

Oracle函数定义示例

CREATE OR REPLACE FUNCTION NAMED_DRIVER_SAVE.FUNC_SAVE_NAMED_DRIVER(
    p_quotation_id IN NUMBER,
    p_driver_name IN VARCHAR2
) RETURN VARCHAR2 AS
BEGIN
    INSERT INTO NAMED_DRIVERS(QUOTATION_ID, DRIVER_NAME) 
    VALUES(p_quotation_id, p_driver_name);
    RETURN '数据保存成功';
EXCEPTION
    WHEN OTHERS THEN
        RETURN '保存失败:' || SQLERRM;
END;

Java调用代码

public void saveNamedDrivers(QuotationDO quotationDO) {
    try {
        System.out.println(" 11111");
        SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(dataSource)
                .withCatalogName("NAMED_DRIVER_SAVE")
                .withFunctionName("FUNC_SAVE_NAMED_DRIVER") // 注意这里用withFunctionName
                .declareParameters(
                        new SqlParameter("p_quotation_id", Types.NUMERIC),
                        new SqlParameter("p_driver_name", Types.VARCHAR)
                );

        Map<String, Object> inParams = new HashMap<>();
        inParams.put("p_quotation_id", quotationDO.getQuotationId());
        inParams.put("p_driver_name", quotationDO.getDriverName());

        // 直接调用executeFunction获取返回值,指定返回值类型
        String result = simpleJdbcCall.executeFunction(String.class, inParams);

        System.out.println("函数返回结果:" + result);
        if (result.startsWith("保存失败")) {
            throw new RuntimeException(result);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

关键注意点

  • 参数名必须和Oracle存储过程/函数中的参数名严格匹配,Oracle默认是大写,所以Java代码中的参数名最好也用大写,避免匹配失败。
  • 要确保dataSource已经正确配置,能够正常连接到Oracle数据库。
  • 如果存储过程需要返回结果集(比如查询数据),可以用SqlReturnResultSet或者SqlOutParameter配合Types.CURSOR来处理。

内容的提问来源于stack exchange,提问作者MohanaKrishnan S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:03:33