2010-01-28 106 views
15

我正在使用Spring的JdbcTemplate和StoredProcedure类。我无法让存储过程类为我工作。Spring的存储过程 - 从过程返回的结果始终为空

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

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; 

我已创建以下存储过程类从Oracle过程

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,因此无法返回。我知道数据库上有符合我输入条件的行。我还有代码工作,它使用java.sql.CallableStatement与oracle存储过程交互 - 所以过程很好。将OraceleTypes.CURSOR与Spring的存储过程混合是不对的?我还能使用什么?我也试过SqlReturnResultSet,那也没用。

回答

7

这里存在的问题是Oracle执行存储过程的方式与JDBC不兼容。 Oracle的SP通过OUT参数或返回值作为游标返回结果集数据,并且必须专门处理它们。这意味着你不能使用任何假定遵从JDBC的JDBC的东西,你必须自己去做。

实际上,这意味着您必须使用JdbcTemplateCallableStatementCallback,这意味着比您理想的更多的手动JDBC编码,但是我还没有找到避免这种情况的方法。我略微怀疑JDBC规范的编写方式与Sybase(以及通过关联SQL Server)的方式密切相关,因为存储过程在JDBC中处理的方式非常明显非常适合这些系统(对甲骨文来说也不太合适)。

+7

嗨,感谢您的反馈。我使用了我的Oracle存储过程。问题出在我声明的输出参数上。以下工作 declareParameter(new SqlOutParameter(“output”,oracle.jdbc.OracleTypes.CURSOR,new RowMapper(){public String mapRow(ResultSet argResults,int argRowNum)throws SQLException {return argResults.getString(1);}}) );这现在正在为我工​​作。谢谢 – aos 2010-01-28 14:14:03

+2

您应该已经回答了您自己的问题,并将其选为接受的答案。无论如何感谢张贴。 – 2012-09-25 17:22:07

4

这个问题很简单,如果你在传递一个CURSOR的outparam时没有传递RowMapper。 Spring将返回{}即空游标。

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

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