Spring 的存储过程 - 从过程返回的结果始终为空

我正在使用Spring的JdbcTemplate和StoredProcedure类。我在使存储过程类为我工作时遇到问题。

我在预言机数据库上有一个存储过程。它的签名是

CREATE OR REPLACE PROCEDURE PRC_GET_USERS_BY_SECTION
(user_cursor OUT Pkg_Types.cursor_type
 , section_option_in IN Varchar2
 , section_in IN Varchar2) AS ....

哪里

TYPE cursor_type IS REF CURSOR;

我创建了以下存储过程类以从预言机过程中获取信息

    private class MyStoredProcedure extends StoredProcedure 
{
    public MyStoredProcedure(JdbcTemplate argJdbcTemplate) 
    {
        super(argJdbcTemplate, "PRC_GET_USERS_BY_SECTION");
        declareParameter(new SqlOutParameter("output", OracleTypes.CURSOR));
        declareParameter(new SqlParameter("input1", Types.VARCHAR));
        declareParameter(new SqlParameter("input2", Types.VARCHAR));
        compile();          
    }


    public Map<String, Object> execute() {

        Map<String, Object> inParams = new HashMap<String, Object>();
        inParams.put("input1", "BG");
        inParams.put("input2", "FE");
        Map output = execute(inParams);
        return output;
    }
}

我在我的一个DAO类中的方法中调用它

    public List<String> getUserListFromProcedure() throws BatchManagerException
{
    MyStoredProcedure sp = new MyStoredProcedure( this.jdbcTemplate );
    Map<String, Object> result = new HashMap<String, Object>();
    try
    {
        result = sp.execute();
    }

    catch( DataAccessException dae) 
    {

    }
    System.out.println(result.size());
    return null;
}

但是,地图的大小始终为 0,因此不会返回任何内容。我知道数据库中有与我的输入条件匹配的行。此外,我有代码工作,用于与oracle存储的proc进行交互 - 所以proc很好。与Spring的存储过程混合是错误的吗?我还能使用什么?我也试过了,这也不起作用。java.sql.CallableStatementOraceleTypes.CURSORSqlReturnResultSet


答案 1

这里的问题是,Oracle 执行存储过程的方式不符合 JDBC 标准。Oracle 的 SP 通过 OUT 参数或游标返回值返回结果集数据,并且必须对其进行特殊处理。这意味着你不能使用任何假设符合JDBC的Spring的JDBC的东西,你必须自己做。

在实践中,这意味着你必须使用 和 ,这意味着手动 JDBC 编码比你理想中想要的要多得多,但我还没有找到一种方法来避免这种情况。JdbcTemplateCallableStatementCallback

顺便说一句,我宁愿怀疑JDBC规范的编写是为了严格遵守Sybase(以及通过关联,SQL Server)的做事方式,因为在JDBC中处理存储过程的方式非常适合这些系统(并且不适合Oracle)。


答案 2

如果你在声明 CURSOR 的 outparam 时不传递 RowMapper,那么问题就很简单了。春天将返回,即空光标。{}

 declareParameter(new SqlOutParameter("output", OracleTypes.CURSOR)); - returns empty {}
 declareParameter(new SqlOutParameter("output", OracleTypes.CURSOR, new ApplicationMapper()); - returns result

其中 ApplicationMapper 是我的自定义映射器,它实现了 RowMapper。


推荐