如何通过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
相关产品推荐
相关产品推荐

