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

发布于 2024-08-19 10:50:00 字数 1818 浏览 8 评论 0原文

我正在使用 Spring 的 JdbcTemplate 和 StoredProcedure 类。我无法让存储过程类为我工作。

我有一个关于 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 但也不起作用。

I am using Spring's JdbcTemplate and StoredProcedure classes. I am having trouble getting the stored procedure class to work for me.

I have a stored procedure on an oracle database. Its signature is

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 ....

where

TYPE cursor_type IS REF CURSOR;

I have create the following stored procedure class to get information from the oracle procedure

    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;
    }
}

I am calling this in a method in one of my DAO classes

    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;
}

However the size of the map is always 0, so nothing comes back. I know that there are rows on the database which match my input criteria. Also I had code working which used java.sql.CallableStatement to interact with the oracle stored proc - so the proc is good. Is it wrong to mix OraceleTypes.CURSOR with Spring's Stored Procedure? What else can I use? I also tried SqlReturnResultSet and that didn't work either.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凶凌 2024-08-26 10:50:00

这里的问题是 Oracle 执行存储过程的方式不符合 JDBC。 Oracle的SP通过OUT参数返回结果集数据或者返回游标值,并且必须对它们进行特殊处理。这意味着您不能使用 Spring 的任何假定符合 JDBC 的 JDBC 内容,您必须自己完成。

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

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

The problem here is that Oracle's way of doing stored procedures is not JDBC compliant. Oracle's SPs return resultset data via OUT parameters or return values that are cursors, and they have to be handled specially. This means you cannot use any of Spring's JDBC stuff that assumes compliance with JDBC, you have to do it yourself.

In practice, this means you have to use JdbcTemplate and CallableStatementCallback, which means a lot more manual JDBC coding than you'd ideally like, but I've yet to find a way to avoid this.

On a slight aside, I rather suspect that the JDBC spec was written to conform closely to the Sybase (and, by association, SQL Server) way of doing things, because the way stored procedures are handled in JDBC is a remarkably good fit for those systems (and a poor fit for Oracle's).

眼眸里的那抹悲凉 2024-08-26 10:50:00

如果在声明作为 CURSOR 的 outparam 时不传递 RowMapper,问题很简单。 Spring 将返回 {} 即空光标。

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

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

The problem is simple if you don't pass a RowMapper while declaring the outparam which is a CURSOR. Spring is going to return {} I.e empty cursor.

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

Where ApplicationMapper is my custom mapper which implements RowMapper.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文