Plantilla Spring JDBC para llamar a procedimientos almacenados

¿Cuál es la forma correcta de invocar los procedimientos almacenados utilizando la plantilla JDBC Spring de la actualidad (circa 2012)?

Diga, tengo un procedimiento almacenado que declara los parámetros IN y OUT , algo como esto:

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

Me he encontrado con los CallableStatementCreator basados ​​en CallableStatementCreator donde tenemos que registrar explícitamente los parámetros IN y OUT . Considere el siguiente método en la clase JdbcTemplate :

 public Map call(CallableStatementCreator csc, List declaredParameters) 

Por supuesto, sé que puedo usarlo así:

 List declaredParameters = new ArrayList(); 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", ""); stmnt.setDate("date", ); return stmnt; } }, declaredParameters); 

¿Cuál es el propósito de los Parámetros declaredParameters cuando ya los estoy registrando en mi implementación de csc ? En otras palabras, ¿por qué tendría que pasar un csc cuando la spring simplemente puede hacer con.prepareCall(sql) internamente? Básicamente, ¿no puedo pasar a ninguno de ellos en lugar de a los dos?

¿O hay una forma mucho mejor de llamar a los procedimientos almacenados (utilizando Spring JDBC Template) que lo que he encontrado hasta ahora?

Nota: Puede encontrar muchas preguntas que parecen tener un título similar, pero no son las mismas que esta.

Hay varias maneras de llamar a los procedimientos almacenados en Spring.

Si usa CallableStatementCreator para declarar parámetros, usará la interfaz estándar de CallableStatement de CallableStatement , es decir, registrará los parámetros y los establecerá por separado. El uso de la abstracción de SqlParameter hará que su código sea más limpio.

Te recomiendo que SimpleJdbcCall . Se puede usar así:

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

Para procedimientos simples puede usar el método de update jdbcTemplate :

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

Estas son las formas de llamar a los procedimientos almacenados desde Java

1. Usando 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(); 

Aquí administramos externamente el cierre del recurso

2. Usando 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 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. Use SimpleJdbcCall:

 SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate) .withProcedureName("STORED_PROCEDURE_NAME"); Map inParamMap = new HashMap(); inParamMap.put("firstName", "FirstNameValue"); inParamMap.put("lastName", "LastNameValue"); SqlParameterSource in = new MapSqlParameterSource(inParamMap); Map simpleJdbcCallResult = simpleJdbcCall.execute(in); System.out.println(simpleJdbcCallResult); 

4. Utilice la clase 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"); 

Referencia

Por lo general, prefiero extender la clase StoredProcedure basada en Spring para ejecutar procedimientos almacenados.

  1. Necesita crear su constructor de clase y necesita llamar al constructor de la clase StoredProcedure . Este constructor de clase superior acepta DataSource y el nombre del procedimiento.

    Código de ejemplo:

     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. Sobrescribir el método de ejecución de llamada a procedimiento almacenado como se muestra a continuación

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

Espero que esto te ayude.

Una forma más de llamar al procedimiento almacenado es:

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

En este ejemplo, ‘ClientInvestigateDTO’ es la clase POJO y ‘ClientInvestigateMapper’ es la clase mapeador.’Client ‘almacena todo el resultado que obtiene al invocar el procedimiento almacenado.