Pergunta

Estou usando as classes JDBCTemplate e StoredProcedure da Spring. Estou tendo problemas para conseguir que a classe de procedimentos armazenados funcione para mim.

Eu tenho um procedimento armazenado em um banco de dados Oracle. Sua assinatura é

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

Onde

TYPE cursor_type IS REF CURSOR;

Eu criei a seguinte classe de procedimento armazenado para obter informações do procedimento 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;
    }
}

Estou chamando isso em um método em uma das minhas aulas de 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;
}

No entanto, o tamanho do mapa é sempre 0, então nada volta. Eu sei que existem linhas no banco de dados que correspondem aos meus critérios de entrada. Também eu tinha código que trabalhava que usava java.sql.CallableStatement Para interagir com o Proc Oracle armazenado - o PROC é bom. É errado misturar OraceleTypes.CURSOR Com o procedimento armazenado da Spring? O que mais posso usar? Eu também tentei SqlReturnResultSet E isso também não funcionou.

Foi útil?

Solução

O problema aqui é que a maneira da Oracle de realizar procedimentos armazenados não é compatível com o JDBC. O SPS de retorno do Oracle DataSet Data por meio de parâmetros ou valores de retorno que são cursores, e eles precisam ser tratados especialmente. Isso significa que você não pode usar qualquer material JDBC da Spring que assuma a conformidade com o JDBC, você precisa fazer isso sozinho.

Na prática, isso significa que você tem que usar JdbcTemplate e CallableStatementCallback, o que significa muito mais codificação JDBC manual do que você gostaria, mas ainda não encontrei uma maneira de evitar isso.

Em um pouco de lado, suspeito que a especificação JDBC tenha sido escrita para estar em conformidade com a maneira Sybase (e, por associação, servidor SQL) de fazer as coisas, porque a maneira como os procedimentos armazenados são tratados no JDBC é um ajuste notavelmente bom para aqueles sistemas (e um mau ajuste para o Oracle's).

Outras dicas

O problema é simples se você não passar por um Rowmapper enquanto declarava o outparam, que é um cursor. A primavera vai voltar {} Ou seja, cursor vazio.

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

Onde o ApplicationMapper é o meu mapeador personalizado, que implementa Rowmapper.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top