95 votes

Modèle de Spring JDBC pour l'appel de procédures stockées

Quelle est la bonne façon d'invoquer des procédures stockées à l'aide du modèle Spring JDBC actuel (vers 2012) ?

Disons que j'ai une procédure stockée qui déclare à la fois IN et OUT paramètres, quelque chose comme ça :

mypkg.doSomething(
    id OUT int,
    name IN String,
    date IN Date
)

Je suis tombé sur CallableStatementCreator où nous devons enregistrer explicitement IN et OUT paramètres. Considérons la méthode suivante dans JdbcTemplate classe :

public Map<String, Object> call(CallableStatementCreator csc, List<SqlParameter> declaredParameters)

Bien sûr, je sais que je peux l'utiliser comme ça :

List<SqlParameter> declaredParameters = new ArrayList<SqlParameter>();

declaredParameters.add(new SqlOutParameter("id", Types.INTEGER));
declaredParameters.add(new SqlParameter("name", Types.VARCHAR));
declaredParameters.add(new SqlParameter("date", Types.DATE));

this.jdbcTemplate.call(new CallableStatementCreator() {

    @Override
    CallableStatement createCallableStatement(Connection con) throws SQLException {
        CallableStatement stmnt = con.createCall("{mypkg.doSomething(?, ?, ?)}");

        stmnt.registerOutParameter("id", Types.INTEGER);
        stmnt.setString("name", "<name>");
        stmnt.setDate("date", <date>);

        return stmnt;
    }
}, declaredParameters);

Quel est le but de declaredParameters alors que je les enregistre déjà dans mon csc mise en œuvre ? En d'autres termes, pourquoi aurais-je besoin de passer dans un fichier csc quand le printemps peut simplement faire con.prepareCall(sql) en interne ? En gros, ne puis-je pas passer dans l'un ou l'autre au lieu des deux ?

Ou bien, existe-t-il un meilleur moyen d'appeler les procédures stockées (en utilisant Spring JDBC Template) que ce que j'ai rencontré jusqu'à présent ?

Nota: Vous trouverez peut-être de nombreuses questions dont le titre semble similaire, mais qui ne sont pas identiques à celle-ci.

4 votes

Je vois que cette question est assez populaire maintenant et cela fait déjà plus de 2 ans qu'elle a été posée. Si quelqu'un pense qu'il existe une façon encore plus agréable d'appeler les procédures stockées maintenant que Spring 4 est sorti, veuillez poster une réponse ou suggérer une modification.

112voto

Infeligo Points 4923

Il existe plusieurs façons d'appeler des procédures stockées dans Spring.

Si vous utilisez CallableStatementCreator pour déclarer des paramètres, vous utiliserez l'interface standard Java de CallableStatement c'est-à-dire enregistrer les paramètres et les régler séparément. Utilisation de SqlParameter L'abstraction rendra votre code plus propre.

Je vous recommande de regarder SimpleJdbcCall . Il peut être utilisé comme suit :

SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
    .withSchemaName(schema)
    .withCatalogName(package)
    .withProcedureName(procedure)();
...
jdbcCall.addDeclaredParameter(new SqlParameter(paramName, OracleTypes.NUMBER));
...
jdbcCall.execute(callParams);

Pour les procédures simples, vous pouvez utiliser jdbcTemplate 's update méthode :

jdbcTemplate.update("call SOME_PROC (?, ?)", param1, param2);

0 votes

SimpleJdbcCall semble vraiment cool. Je vais le tester et vous faire savoir comment cela s'est passé dans mon cas.

2 votes

La méthode de mise à jour n'a pas fonctionné pour moi, j'ai reçu une exception de mauvaise grammaire SQL alors que ma déclaration s'exécutait parfaitement dans la base de données. SimpleJdbcCall a très bien fonctionné.

0 votes

J'essaie d'utiliser jdbcTemplate.update() de la même manière que vous l'avez dit, mais j'obtiens l'erreur suivante "cannot invoke update on null object" .

66voto

Sairam Kukadala Points 671

Voici les moyens d'appeler les procédures stockées à partir de java

1. Utilisation de CallableStatement :

 connection = jdbcTemplate.getDataSource().getConnection();
  CallableStatement callableStatement = connection.prepareCall("{call STORED_PROCEDURE_NAME(?, ?, ?)}");
  callableStatement.setString(1, "FirstName");
  callableStatement.setString(2, " LastName");
  callableStatement.registerOutParameter(3, Types.VARCHAR);
  callableStatement.executeUpdate();

Ici, nous gérons en externe la fermeture de la ressource

2. Utilisation du CallableStatementCreator

 List paramList = new ArrayList();
    paramList.add(new SqlParameter(Types.VARCHAR));
    paramList.add(new SqlParameter(Types.VARCHAR));
    paramList.add(new SqlOutParameter("msg", Types.VARCHAR));

    Map<String, Object> resultMap = jdbcTemplate.call(new CallableStatementCreator() {

    @Override
    public CallableStatement createCallableStatement(Connection connection)
    throws SQLException {

    CallableStatement callableStatement = connection.prepareCall("{call STORED_PROCEDURE_NAME(?, ?, ?)}");
    callableStatement.setString(1, "FirstName");
            callableStatement.setString(2, " LastName");
            callableStatement.registerOutParameter(3, Types.VARCHAR);
    return callableStatement;

    }
    }, paramList);

3. Utilisez SimpleJdbcCall :

SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate)

.withProcedureName("STORED_PROCEDURE_NAME");

Map<String, Object> inParamMap = new HashMap<String, Object>();
inParamMap.put("firstName", "FirstNameValue");
inParamMap.put("lastName", "LastNameValue");
SqlParameterSource in = new MapSqlParameterSource(inParamMap);

Map<String, Object> simpleJdbcCallResult = simpleJdbcCall.execute(in);
System.out.println(simpleJdbcCallResult);

4. Utilisation de la classe StoredProcedure de org.springframework.jdbc.object

The Code:
First Create subclass of StoredProcedure: MyStoredProcedure

class MyStoredProcedure extends StoredProcedure {

public MyStoredProcedure(JdbcTemplate jdbcTemplate, String name) {

super(jdbcTemplate, name);
setFunction(false);

}

}

Use MyStoredProcedure to call database stored procedure:

//Pass jdbcTemlate and name of the stored Procedure.
MyStoredProcedure myStoredProcedure = new MyStoredProcedure(jdbcTemplate, "PROC_TEST");

//Sql parameter mapping
SqlParameter fNameParam = new SqlParameter("fName", Types.VARCHAR);
SqlParameter lNameParam = new SqlParameter("lName", Types.VARCHAR);
SqlOutParameter msgParam = new SqlOutParameter("msg", Types.VARCHAR);
SqlParameter[] paramArray = {fNameParam, lNameParam, msgParam};

myStoredProcedure.setParameters(paramArray);
myStoredProcedure.compile();

//Call stored procedure
Map storedProcResult = myStoredProcedure.execute("FirstNameValue", " LastNameValue");

Référence

22voto

VivekDandale Points 41

En général, je préfère étendre les applications basées sur Spring StoredProcedure pour exécuter des procédures stockées.

  1. Vous devez créer le constructeur de votre classe et appeler StoredProcedure dans le constructeur de la classe. Ce constructeur de super classe accepte DataSource et le nom de la procédure.

    Exemple de code :

    public class ProcedureExecutor extends StoredProcedure {
          public ProcedureExecutor(DataSource ds, String funcNameorSPName) {
            super(ds, funcNameorSPName);
            declareParameter(new SqlOutParameter("v_Return", Types.VARCHAR, null, new SqlReturnType() {
                    public Object getTypeValue(CallableStatement cs,
                         int paramIndex, int sqlType, String typeName) throws SQLException {
                    final String str = cs.getString(paramIndex);
                    return str;
                }           
            }));    
            declareParameter(new SqlParameter("your parameter",
                    Types.VARCHAR));
            //set below param true if you want to call database function 
            setFunction(true);
            compile();
            }
  2. Remplacer la méthode execute de l'appel de la procédure stockée comme ci-dessous

    public Map<String, Object> execute(String someParams) {
                 final Map<String, Object> inParams = new HashMap<String, Object>(8);
                 inParams.put("my param", "some value");
                 Map outMap = execute(inParams);
                 System.out.println("outMap:" + outMap);
                 return outMap;
             }

J'espère que cela vous aidera.

4voto

Aditee Points 31

Une autre façon d'appeler la procédure stockée est :

sql="execute Procedure_Name ?";
Object search[]={Id};
List<ClientInvestigateDTO> client=jdbcTemplateObject.query(sql,search,new 
   ClientInvestigateMapper());

Dans cet exemple, 'ClientInvestigateDTO' est la classe POJO et 'ClientInvestigateMapper' est la classe mapper. 'client' stocke tous les résultats que vous obtenez en appelant la procédure stockée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X