2010-01-28 5 views
15

J'utilise les classes JdbcTemplate et StoredProcedure de Spring. J'ai du mal à faire fonctionner la classe de procédure stockée pour moi.Procédure stockée de Spring - les résultats de la procédure sont toujours vides

J'ai une procédure stockée sur une base de données Oracle. Sa signature est

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; 

Je crée la classe de procédure stockée suivante pour obtenir des informations de la procédure 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; 
    } 
} 

J'appelle cela dans une méthode dans l'un des mes classes 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; 
} 

Cependant, la taille de la carte est toujours 0, donc rien ne revient. Je sais qu'il y a des lignes dans la base de données qui correspondent à mes critères d'entrée. En outre, j'ai eu le code de travail qui a utilisé java.sql.CallableStatement pour interagir avec le proc stocké oracle - donc le proc est bon. Est-ce mal de mélanger OraceleTypes.CURSOR avec la procédure stockée de Spring? Que puis-je utiliser d'autre? J'ai également essayé SqlReturnResultSet et cela n'a pas fonctionné non plus.

Répondre

7

Le problème ici est que la façon dont Oracle exécute les procédures stockées n'est pas compatible avec JDBC. Les SP d'Oracle renvoient des données de jeu de résultats via des paramètres OUT ou des valeurs de retour qui sont des curseurs, et ils doivent être gérés spécialement. Cela signifie que vous ne pouvez utiliser aucun des éléments JDBC de Spring qui suppose la conformité avec JDBC, vous devez le faire vous-même. En pratique, cela signifie que vous devez utiliser JdbcTemplate et CallableStatementCallback, ce qui signifie beaucoup plus de codage JDBC manuel que vous le souhaiteriez, mais je n'ai pas encore trouvé de moyen d'éviter cela. En passant, je soupçonne plutôt que la spécification JDBC a été écrite pour se conformer étroitement à la façon de procéder de Sybase (et, par association, SQL Server), parce que la façon dont les procédures stockées sont traitées dans JDBC est remarquablement bon ajustement pour ces systèmes (et un mauvais ajustement pour Oracle).

+7

Salut, Merci pour vos commentaires. J'ai eu ce travail avec ma procédure stockée Oracle. Le problème était avec le paramètre de sortie que j'avais déclaré. Les travaux suivants declareParameter (new SqlOutParameter ("output", oracle.jdbc.OracleTypes.CURSOR, new RowMapper() {chaîne publique mapRow (ResultSet argResults, int argRowNum) throws SQLException {return argResults.getString (1);}})) Cela fonctionne pour moi maintenant. Merci – aos

+2

Vous auriez dû répondre à votre propre question et l'avoir sélectionnée comme réponse acceptée. Merci de poster quand même. –

4

Le problème est simple si vous ne passez pas un RowMapper lors de la déclaration de l'outparam qui est un curseur. Le ressort va retourner {} I.e curseur vide.

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

Où ApplicationMapper est mon mappeur personnalisé qui implémente RowMapper.

Questions connexes