web-dev-qa-db-fra.com

Modèle JDBC Spring 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 Spring (circa 2012)?

Dites, j'ai une procédure stockée qui déclare les deux paramètres IN et OUT, quelque chose comme ceci:

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

J'ai rencontré des approches basées sur CallableStatementCreator où nous devons explicitement enregistrer les paramètres IN et OUT. Considérez la méthode suivante dans la classe JdbcTemplate:

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

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

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 implémentation csc? En d'autres termes, pourquoi aurais-je besoin de passer un csc alors que le printemps peut simplement faire con.prepareCall(sql) en interne? Fondamentalement, ne puis-je pas passer l'un ou l'autre au lieu des deux?

Ou bien, existe-t-il un bien meilleur moyen d'appeler des procédures stockées (à l'aide du modèle Spring JDBC) que ce que j'ai rencontré jusqu'à présent?

Note: Vous pouvez trouver beaucoup de questions qui semblent avoir un titre similaire mais ne sont pas les mêmes que celle-ci.

69
adarshr

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

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

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

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 la méthode jdbcTemplate de update:

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

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 des ressources

2. Utilisation de 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. Utilisez 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

27
Sairam Kukadala

Je préfère généralement étendre la classe StoredProcedure basée sur Spring pour exécuter des procédures stockées.

  1. Vous devez créer votre constructeur de classe et y appeler StoredProcedure constructeur de classe. Ce constructeur de super classe accepte DataSource et nom de 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 d'exécution de l'appel de 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 aide.

17
VivekDandale

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

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 de mappeur. "Client" stocke tous les résultats obtenus lors de l'appel de la procédure stockée.

1
Aditee