Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * Copyright 2002-2010 the original author or authors.
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    *      http://www.apache.org/licenses/LICENSE-2.0
    *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.springframework.jdbc.core;
  
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
This is the central class in the JDBC core package. It simplifies the use of JDBC and helps to avoid common errors. It executes core JDBC workflow, leaving application code to provide SQL and extract results. This class executes SQL queries or updates, initiating iteration over ResultSets and catching JDBC exceptions and translating them to the generic, more informative exception hierarchy defined in the org.springframework.dao package.

Code using this class need only implement callback interfaces, giving them a clearly defined contract. The PreparedStatementCreator callback interface creates a prepared statement given a Connection, providing SQL and any necessary parameters. The ResultSetExtractor interface extracts values from a ResultSet. See also PreparedStatementSetter and RowMapper for two popular alternative callback interfaces.

Can be used within a service implementation via direct instantiation with a DataSource reference, or get prepared in an application context and given to services as bean reference. Note: The DataSource should always be configured as a bean in the application context, in the first case given to the service directly, in the second case to the prepared template.

Because this class is parameterizable by the callback interfaces and the org.springframework.jdbc.support.SQLExceptionTranslator interface, there should be no need to subclass it.

All SQL operations performed by this class are logged at debug level, using "org.springframework.jdbc.core.JdbcTemplate" as log category.

  
  public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
  
  	private static final String RETURN_RESULT_SET_PREFIX = "#result-set-";
  
  	private static final String RETURN_UPDATE_COUNT_PREFIX = "#update-count-";


Custom NativeJdbcExtractor
 
If this variable is false, we will throw exceptions on SQL warnings
 
 	private boolean ignoreWarnings = true;

If this variable is set to a non-zero value, it will be used for setting the fetchSize property on statements used for query processing.
 
 	private int fetchSize = 0;

If this variable is set to a non-zero value, it will be used for setting the maxRows property on statements used for query processing.
 
 	private int maxRows = 0;

If this variable is set to a non-zero value, it will be used for setting the queryTimeout property on statements used for query processing.
 
 	private int queryTimeout = 0;

If this variable is set to true then all results checking will be bypassed for any callable statement processing. This can be used to avoid a bug in some older Oracle JDBC drivers like 10.1.0.2.
 
 	private boolean skipResultsProcessing = false;

If this variable is set to true then all results from a stored procedure call that don't have a corresponding SqlOutParameter declaration will be bypassed. All other results processng will be take place unless the variable skipResultsProcessing is set to true
 
 	private boolean skipUndeclaredResults = false;

If this variable is set to true then execution of a CallableStatement will return the results in a Map that uses case insensitive names for the parameters if Commons Collections is available on the classpath.
 
 	private boolean resultsMapCaseInsensitive = false;


Construct a new JdbcTemplate for bean usage.

Note: The DataSource has to be set before using the instance.

 
 	public JdbcTemplate() {
 	}

Construct a new JdbcTemplate, given a DataSource to obtain connections from.

Note: This will not trigger initialization of the exception translator.

Parameters:
dataSource the JDBC DataSource to obtain connections from
 
 	public JdbcTemplate(DataSource dataSource) {
 		setDataSource(dataSource);
 	}

Construct a new JdbcTemplate, given a DataSource to obtain connections from.

Note: Depending on the "lazyInit" flag, initialization of the exception translator will be triggered.

Parameters:
dataSource the JDBC DataSource to obtain connections from
lazyInit whether to lazily initialize the SQLExceptionTranslator
 
 	public JdbcTemplate(DataSource dataSourceboolean lazyInit) {
 		setDataSource(dataSource);
 		setLazyInit(lazyInit);
 	}


Set a NativeJdbcExtractor to extract native JDBC objects from wrapped handles. Useful if native Statement and/or ResultSet handles are expected for casting to database-specific implementation classes, but a connection pool that wraps JDBC objects is used (note: any pool will return wrapped Connections).
 
 	public void setNativeJdbcExtractor(NativeJdbcExtractor extractor) {
 		this. = extractor;
 	}

Return the current NativeJdbcExtractor implementation.
 
 		return this.;
 	}

Set whether or not we want to ignore SQLWarnings.

Default is "true", swallowing and logging all warnings. Switch this flag to "false" to make the JdbcTemplate throw a SQLWarningException instead.

 
 	public void setIgnoreWarnings(boolean ignoreWarnings) {
 		this. = ignoreWarnings;
 	}

Return whether or not we ignore SQLWarnings.
 
 	public boolean isIgnoreWarnings() {
 		return this.;
 	}

Set the fetch size for this JdbcTemplate. This is important for processing large result sets: Setting this higher than the default value will increase processing speed at the cost of memory consumption; setting this lower can avoid transferring row data that will never be read by the application.

Default is 0, indicating to use the JDBC driver's default.

 
 	public void setFetchSize(int fetchSize) {
 		this. = fetchSize;
 	}

Return the fetch size specified for this JdbcTemplate.
 
 	public int getFetchSize() {
 		return this.;
 	}

Set the maximum number of rows for this JdbcTemplate. This is important for processing subsets of large result sets, avoiding to read and hold the entire result set in the database or in the JDBC driver if we're never interested in the entire result in the first place (for example, when performing searches that might return a large number of matches).

Default is 0, indicating to use the JDBC driver's default.

 
 	public void setMaxRows(int maxRows) {
 		this. = maxRows;
 	}

Return the maximum number of rows specified for this JdbcTemplate.
 
 	public int getMaxRows() {
 		return this.;
 	}

Set the query timeout for statements that this JdbcTemplate executes.

Default is 0, indicating to use the JDBC driver's default.

Note: Any timeout specified here will be overridden by the remaining transaction timeout when executing within a transaction that has a timeout specified at the transaction level.

 
 	public void setQueryTimeout(int queryTimeout) {
 		this. = queryTimeout;
 	}

Return the query timeout for statements that this JdbcTemplate executes.
 
 	public int getQueryTimeout() {
 		return this.;
 	}

Set whether results processing should be skipped. Can be used to optimize callable statement processing when we know that no results are being passed back - the processing of out parameter will still take place. This can be used to avoid a bug in some older Oracle JDBC drivers like 10.1.0.2.
 
 	public void setSkipResultsProcessing(boolean skipResultsProcessing) {
 		this. = skipResultsProcessing;
 	}

Return whether results processing should be skipped.
 
 	public boolean isSkipResultsProcessing() {
 		return this.;
 	}

Set whether undelared results should be skipped.
 
 	public void setSkipUndeclaredResults(boolean skipUndeclaredResults) {
 		this. = skipUndeclaredResults;
 	}

Return whether undeclared results should be skipped.
 
 	public boolean isSkipUndeclaredResults() {
 		return this.;
 	}

Set whether execution of a CallableStatement will return the results in a Map that uses case insensitive names for the parameters.
 
 	public void setResultsMapCaseInsensitive(boolean resultsMapCaseInsensitive) {
 		this. = resultsMapCaseInsensitive;
 	}

Return whether execution of a CallableStatement will return the results in a Map that uses case insensitive names for the parameters.
 
 	public boolean isResultsMapCaseInsensitive() {
 	}
 
 
 	//-------------------------------------------------------------------------
 	// Methods dealing with a plain java.sql.Connection
 	//-------------------------------------------------------------------------
 
 	public <T> T execute(ConnectionCallback<T> actionthrows DataAccessException {
 		Assert.notNull(action"Callback object must not be null");
 
 		Connection con = DataSourceUtils.getConnection(getDataSource());
 		try {
 			Connection conToUse = con;
 			if (this. != null) {
 				// Extract native JDBC Connection, castable to OracleConnection or the like.
 				conToUse = this..getNativeConnection(con);
 			}
 			else {
 				// Create close-suppressing Connection proxy, also preparing returned Statements.
 				conToUse = createConnectionProxy(con);
 			}
 			return action.doInConnection(conToUse);
 		}
 		catch (SQLException ex) {
 			// Release Connection early, to avoid potential connection pool deadlock
 			// in the case when the exception translator hasn't been initialized yet.
 			DataSourceUtils.releaseConnection(congetDataSource());
 			con = null;
 			throw getExceptionTranslator().translate("ConnectionCallback"getSql(action), ex);
 		}
 		finally {
 			DataSourceUtils.releaseConnection(congetDataSource());
 		}
 	}

Create a close-suppressing proxy for the given JDBC Connection. Called by the execute method.

The proxy also prepares returned JDBC Statements, applying statement settings such as fetch size, max rows, and query timeout.

Parameters:
con the JDBC Connection to create a proxy for
Returns:
the Connection proxy
See also:
java.sql.Connection.close()
execute(org.springframework.jdbc.core.ConnectionCallback)
applyStatementSettings(java.sql.Statement)
 
 		return (Connection) Proxy.newProxyInstance(
 				new Class[] {ConnectionProxy.class},
 	}
 
 
 	//-------------------------------------------------------------------------
 	// Methods dealing with static SQL (java.sql.Statement)
 	//-------------------------------------------------------------------------
 
 	public <T> T execute(StatementCallback<T> actionthrows DataAccessException {
 		Assert.notNull(action"Callback object must not be null");
 
 		Connection con = DataSourceUtils.getConnection(getDataSource());
 		Statement stmt = null;
 		try {
 			Connection conToUse = con;
 			if (this. != null &&
 				conToUse = this..getNativeConnection(con);
 			}
 			stmt = conToUse.createStatement();
 			Statement stmtToUse = stmt;
 			if (this. != null) {
 				stmtToUse = this..getNativeStatement(stmt);
 			}
 			T result = action.doInStatement(stmtToUse);
 			return result;
 		}
 		catch (SQLException ex) {
 			// Release Connection early, to avoid potential connection pool deadlock
 			// in the case when the exception translator hasn't been initialized yet.
 			JdbcUtils.closeStatement(stmt);
 			stmt = null;
 			DataSourceUtils.releaseConnection(congetDataSource());
 			con = null;
 			throw getExceptionTranslator().translate("StatementCallback"getSql(action), ex);
 		}
 		finally {
 			JdbcUtils.closeStatement(stmt);
 			DataSourceUtils.releaseConnection(congetDataSource());
 		}
 	}
 
 	public void execute(final String sqlthrows DataAccessException {
 			.debug("Executing SQL statement [" + sql + "]");
 		}
 			public Object doInStatement(Statement stmtthrows SQLException {
 				stmt.execute(sql);
 				return null;
 			}
 			public String getSql() {
 				return sql;
 			}
 		}
 	}
 
 	public <T> T query(final String sqlfinal ResultSetExtractor<T> rsethrows DataAccessException {
 		Assert.notNull(sql"SQL must not be null");
 		Assert.notNull(rse"ResultSetExtractor must not be null");
 			.debug("Executing SQL query [" + sql + "]");
 		}
 			public T doInStatement(Statement stmtthrows SQLException {
 				ResultSet rs = null;
 				try {
 					rs = stmt.executeQuery(sql);
 					ResultSet rsToUse = rs;
 					if ( != null) {
 					}
 					return rse.extractData(rsToUse);
 				}
 				finally {
 					JdbcUtils.closeResultSet(rs);
 				}
 			}
 			public String getSql() {
 				return sql;
 			}
 		}
 	}
 
 	public void query(String sqlRowCallbackHandler rchthrows DataAccessException {
 	}
 
 	public <T> List<T> query(String sqlRowMapper<T> rowMapperthrows DataAccessException {
 		return query(sqlnew RowMapperResultSetExtractor<T>(rowMapper));
 	}
 
 	public Map<StringObjectqueryForMap(String sqlthrows DataAccessException {
 	}
 
 	public <T> T queryForObject(String sqlRowMapper<T> rowMapperthrows DataAccessException {
 		List<T> results = query(sqlrowMapper);
 		return DataAccessUtils.requiredSingleResult(results);
 	}
 
 	public <T> T queryForObject(String sqlClass<T> requiredTypethrows DataAccessException {
 		return queryForObject(sqlgetSingleColumnRowMapper(requiredType));
 	}
 
 	public long queryForLong(String sqlthrows DataAccessException {
 		Number number = queryForObject(sqlLong.class);
 		return (number != null ? number.longValue() : 0);
 	}
 
 	public int queryForInt(String sqlthrows DataAccessException {
 		Number number = queryForObject(sqlInteger.class);
 		return (number != null ? number.intValue() : 0);
 	}
 
 	public <T> List<T> queryForList(String sqlClass<T> elementTypethrows DataAccessException {
 		return query(sqlgetSingleColumnRowMapper(elementType));
 	}
 
 	public List<Map<StringObject>> queryForList(String sqlthrows DataAccessException {
 		return query(sqlgetColumnMapRowMapper());
 	}
 
 		return query(sqlnew SqlRowSetResultSetExtractor());
 	}
 
 	public int update(final String sqlthrows DataAccessException {
 		Assert.notNull(sql"SQL must not be null");
 			.debug("Executing SQL update [" + sql + "]");
 		}
 			public Integer doInStatement(Statement stmtthrows SQLException {
 				int rows = stmt.executeUpdate(sql);
 					.debug("SQL update affected " + rows + " rows");
 				}
 				return rows;
 			}
 			public String getSql() {
 				return sql;
 			}
 		}
 	}
 
 	public int[] batchUpdate(final String[] sqlthrows DataAccessException {
 		Assert.notEmpty(sql"SQL array must not be empty");
 			.debug("Executing SQL batch update of " + sql.length + " statements");
 		}
 			private String currSql;
 			public int[] doInStatement(Statement stmtthrows SQLExceptionDataAccessException {
 				int[] rowsAffected = new int[sql.length];
 				if (JdbcUtils.supportsBatchUpdates(stmt.getConnection())) {
 					for (String sqlStmt : sql) {
 						this. = sqlStmt;
 						stmt.addBatch(sqlStmt);
 					}
 					rowsAffected = stmt.executeBatch();
 				}
 				else {
 					for (int i = 0; i < sql.lengthi++) {
 						this. = sql[i];
 						if (!stmt.execute(sql[i])) {
 							rowsAffected[i] = stmt.getUpdateCount();
 						}
 						else {
 							throw new InvalidDataAccessApiUsageException("Invalid batch SQL statement: " + sql[i]);
 						}
 					}
 				}
 				return rowsAffected;
 			}
 			public String getSql() {
 				return this.;
 			}
 		}
 	}
 
 
 	//-------------------------------------------------------------------------
 	// Methods dealing with prepared statements
 	//-------------------------------------------------------------------------
 
 	public <T> T execute(PreparedStatementCreator pscPreparedStatementCallback<T> action)
 
 		Assert.notNull(psc"PreparedStatementCreator must not be null");
 		Assert.notNull(action"Callback object must not be null");
 			String sql = getSql(psc);
 			.debug("Executing prepared SQL statement" + (sql != null ? " [" + sql + "]" : ""));
 		}
 
 		Connection con = DataSourceUtils.getConnection(getDataSource());
 		PreparedStatement ps = null;
 		try {
 			Connection conToUse = con;
 			if (this. != null &&
 				conToUse = this..getNativeConnection(con);
 			}
 			ps = psc.createPreparedStatement(conToUse);
 			PreparedStatement psToUse = ps;
 			if (this. != null) {
 			}
 			T result = action.doInPreparedStatement(psToUse);
 			return result;
 		}
 		catch (SQLException ex) {
 			// Release Connection early, to avoid potential connection pool deadlock
 			// in the case when the exception translator hasn't been initialized yet.
 			if (psc instanceof ParameterDisposer) {
 			}
 			String sql = getSql(psc);
 			psc = null;
 			JdbcUtils.closeStatement(ps);
 			ps = null;
 			DataSourceUtils.releaseConnection(congetDataSource());
 			con = null;
 			throw getExceptionTranslator().translate("PreparedStatementCallback"sqlex);
 		}
 		finally {
 			if (psc instanceof ParameterDisposer) {
 			}
 			JdbcUtils.closeStatement(ps);
 			DataSourceUtils.releaseConnection(congetDataSource());
 		}
 	}
 
 	public <T> T execute(String sqlPreparedStatementCallback<T> actionthrows DataAccessException {
 		return execute(new SimplePreparedStatementCreator(sql), action);
 	}

Query using a prepared statement, allowing for a PreparedStatementCreator and a PreparedStatementSetter. Most other query methods use this method, but application code will always work with either a creator or a setter.

Parameters:
psc Callback handler that can create a PreparedStatement given a Connection
pss object that knows how to set values on the prepared statement. If this is null, the SQL will be assumed to contain no bind parameters.
rse object that will extract results.
Returns:
an arbitrary result object, as returned by the ResultSetExtractor
Throws:
org.springframework.dao.DataAccessException if there is any problem
 
 	public <T> T query(
 
 		Assert.notNull(rse"ResultSetExtractor must not be null");
 		.debug("Executing prepared SQL query");
 
 		return execute(pscnew PreparedStatementCallback<T>() {
 				ResultSet rs = null;
 				try {
 					if (pss != null) {
 						pss.setValues(ps);
 					}
 					rs = ps.executeQuery();
 					ResultSet rsToUse = rs;
 					if ( != null) {
 					}
 					return rse.extractData(rsToUse);
 				}
 				finally {
 					JdbcUtils.closeResultSet(rs);
 					if (pss instanceof ParameterDisposer) {
 					}
 				}
 			}
 		});
 	}
 
 	public <T> T query(PreparedStatementCreator pscResultSetExtractor<T> rsethrows DataAccessException {
 		return query(pscnullrse);
 	}
 
 	public <T> T query(String sqlPreparedStatementSetter pssResultSetExtractor<T> rsethrows DataAccessException {
 		return query(new SimplePreparedStatementCreator(sql), pssrse);
 	}
 
 	public <T> T query(String sqlObject[] argsint[] argTypesResultSetExtractor<T> rsethrows DataAccessException {
 		return query(sqlnewArgTypePreparedStatementSetter(argsargTypes), rse);
 	}
 
 	public <T> T query(String sqlObject[] argsResultSetExtractor<T> rsethrows DataAccessException {
 		return query(sqlnewArgPreparedStatementSetter(args), rse);
 	}
 
 	public <T> T query(String sqlResultSetExtractor<T> rseObject... argsthrows DataAccessException {
 		return query(sqlnewArgPreparedStatementSetter(args), rse);
 	}
 
 	}
 
 	public void query(String sqlPreparedStatementSetter pssRowCallbackHandler rchthrows DataAccessException {
 	}
 
 	public void query(String sqlObject[] argsint[] argTypesRowCallbackHandler rchthrows DataAccessException {
 		query(sqlnewArgTypePreparedStatementSetter(argsargTypes), rch);
 	}
 
 	public void query(String sqlObject[] argsRowCallbackHandler rchthrows DataAccessException {
 	}
 
 	public void query(String sqlRowCallbackHandler rchObject... argsthrows DataAccessException {
 	}
 
 	public <T> List<T> query(PreparedStatementCreator pscRowMapper<T> rowMapperthrows DataAccessException {
 		return query(pscnew RowMapperResultSetExtractor<T>(rowMapper));
 	}
 
 	public <T> List<T> query(String sqlPreparedStatementSetter pssRowMapper<T> rowMapperthrows DataAccessException {
 		return query(sqlpssnew RowMapperResultSetExtractor<T>(rowMapper));
 	}
 
 	public <T> List<T> query(String sqlObject[] argsint[] argTypesRowMapper<T> rowMapperthrows DataAccessException {
 		return query(sqlargsargTypesnew RowMapperResultSetExtractor<T>(rowMapper));
 	}
 
 	public <T> List<T> query(String sqlObject[] argsRowMapper<T> rowMapperthrows DataAccessException {
 		return query(sqlargsnew RowMapperResultSetExtractor<T>(rowMapper));
 	}
 
 	public <T> List<T> query(String sqlRowMapper<T> rowMapperObject... argsthrows DataAccessException {
 		return query(sqlargsnew RowMapperResultSetExtractor<T>(rowMapper));
 	}
 
 	public <T> T queryForObject(String sqlObject[] argsint[] argTypesRowMapper<T> rowMapper)
 
 		List<T> results = query(sqlargsargTypesnew RowMapperResultSetExtractor<T>(rowMapper, 1));
 		return DataAccessUtils.requiredSingleResult(results);
 	}
 
 	public <T> T queryForObject(String sqlObject[] argsRowMapper<T> rowMapperthrows DataAccessException {
 		List<T> results = query(sqlargsnew RowMapperResultSetExtractor<T>(rowMapper, 1));
 		return DataAccessUtils.requiredSingleResult(results);
 	}
 
 	public <T> T queryForObject(String sqlRowMapper<T> rowMapperObject... argsthrows DataAccessException {
 		List<T> results = query(sqlargsnew RowMapperResultSetExtractor<T>(rowMapper, 1));
 		return DataAccessUtils.requiredSingleResult(results);
 	}
 
 	public <T> T queryForObject(String sqlObject[] argsint[] argTypesClass<T> requiredType)
 
 		return queryForObject(sqlargsargTypesgetSingleColumnRowMapper(requiredType));
 	}
 
 	public <T> T queryForObject(String sqlObject[] argsClass<T> requiredTypethrows DataAccessException {
 		return queryForObject(sqlargsgetSingleColumnRowMapper(requiredType));
 	}
 
 	public <T> T queryForObject(String sqlClass<T> requiredTypeObject... argsthrows DataAccessException {
 		return queryForObject(sqlargsgetSingleColumnRowMapper(requiredType));
 	}
 
 	public Map<StringObjectqueryForMap(String sqlObject[] argsint[] argTypesthrows DataAccessException {
 		return queryForObject(sqlargsargTypesgetColumnMapRowMapper());
 	}
 
 	public Map<StringObjectqueryForMap(String sqlObject... argsthrows DataAccessException {
 		return queryForObject(sqlargsgetColumnMapRowMapper());
 	}
 
 	public long queryForLong(String sqlObject[] argsint[] argTypesthrows DataAccessException {
 		Number number = queryForObject(sqlargsargTypesLong.class);
 		return (number != null ? number.longValue() : 0);
 	}
 
 	public long queryForLong(String sqlObject... argsthrows DataAccessException {
 		Number number = queryForObject(sqlargsLong.class);
 		return (number != null ? number.longValue() : 0);
 	}
 
 	public int queryForInt(String sqlObject[] argsint[] argTypesthrows DataAccessException {
 		Number number = queryForObject(sqlargsargTypesInteger.class);
 		return (number != null ? number.intValue() : 0);
 	}
 
 	public int queryForInt(String sqlObject... argsthrows DataAccessException {
 		Number number = queryForObject(sqlargsInteger.class);
 		return (number != null ? number.intValue() : 0);
 	}
 
 	public <T> List<T> queryForList(String sqlObject[] argsint[] argTypesClass<T> elementTypethrows DataAccessException {
 		return query(sqlargsargTypesgetSingleColumnRowMapper(elementType));
 	}
 
 	public <T> List<T> queryForList(String sqlObject[] argsClass<T> elementTypethrows DataAccessException {
 		return query(sqlargsgetSingleColumnRowMapper(elementType));
 	}
 
 	public <T> List<T> queryForList(String sqlClass<T> elementTypeObject... argsthrows DataAccessException {
 		return query(sqlargsgetSingleColumnRowMapper(elementType));
 	}
 
 	public List<Map<StringObject>> queryForList(String sqlObject[] argsint[] argTypesthrows DataAccessException {
 		return query(sqlargsargTypesgetColumnMapRowMapper());
 	}
 
 	public List<Map<StringObject>> queryForList(String sqlObject... argsthrows DataAccessException {
 		return query(sqlargsgetColumnMapRowMapper());
 	}
 
 	public SqlRowSet queryForRowSet(String sqlObject[] argsint[] argTypesthrows DataAccessException {
 		return query(sqlargsargTypesnew SqlRowSetResultSetExtractor());
 	}
 
 	public SqlRowSet queryForRowSet(String sqlObject... argsthrows DataAccessException {
 		return query(sqlargsnew SqlRowSetResultSetExtractor());
 	}
 
 	protected int update(final PreparedStatementCreator pscfinal PreparedStatementSetter pss)
 
 		.debug("Executing prepared SQL update");
 		return execute(pscnew PreparedStatementCallback<Integer>() {
 				try {
 					if (pss != null) {
 						pss.setValues(ps);
 					}
 					int rows = ps.executeUpdate();
 						.debug("SQL update affected " + rows + " rows");
 					}
 					return rows;
 				}
 				finally {
 					if (pss instanceof ParameterDisposer) {
 					}
 				}
 			}
 		});
 	}
 
 	public int update(PreparedStatementCreator pscthrows DataAccessException {
 		return update(psc, (PreparedStatementSetternull);
 	}
 
 	public int update(final PreparedStatementCreator pscfinal KeyHolder generatedKeyHolder)
 
 		Assert.notNull(generatedKeyHolder"KeyHolder must not be null");
 		.debug("Executing SQL update and returning generated keys");
 
 		return execute(pscnew PreparedStatementCallback<Integer>() {
 				int rows = ps.executeUpdate();
 				List<Map<StringObject>> generatedKeys = generatedKeyHolder.getKeyList();
 				generatedKeys.clear();
 				ResultSet keys = ps.getGeneratedKeys();
 				if (keys != null) {
 					try {
 						generatedKeys.addAll(rse.extractData(keys));
 					}
 					finally {
 						JdbcUtils.closeResultSet(keys);
 					}
 				}
 					.debug("SQL update affected " + rows + " rows and returned " + generatedKeys.size() + " keys");
 				}
 				return rows;
 			}
 		});
 	}
 
 	public int update(String sqlPreparedStatementSetter pssthrows DataAccessException {
 		return update(new SimplePreparedStatementCreator(sql), pss);
 	}
 
 	public int update(String sqlObject[] argsint[] argTypesthrows DataAccessException {
 		return update(sqlnewArgTypePreparedStatementSetter(argsargTypes));
 	}
 
 	public int update(String sqlObject... argsthrows DataAccessException {
 		return update(sqlnewArgPreparedStatementSetter(args));
 	}
 
 	public int[] batchUpdate(String sqlfinal BatchPreparedStatementSetter pssthrows DataAccessException {
 			.debug("Executing SQL batch update [" + sql + "]");
 		}
 
 		return execute(sqlnew PreparedStatementCallback<int[]>() {
 			public int[] doInPreparedStatement(PreparedStatement psthrows SQLException {
 				try {
 					int batchSize = pss.getBatchSize();
 					if (JdbcUtils.supportsBatchUpdates(ps.getConnection())) {
 						for (int i = 0; i < batchSizei++) {
 							pss.setValues(psi);
 							if (ipss != null && ipss.isBatchExhausted(i)) {
 								break;
 							}
 							ps.addBatch();
 						}
 						return ps.executeBatch();
 					}
 					else {
 						List<IntegerrowsAffected = new ArrayList<Integer>();
 						for (int i = 0; i < batchSizei++) {
 							pss.setValues(psi);
 							if (ipss != null && ipss.isBatchExhausted(i)) {
 								break;
 							}
 							rowsAffected.add(ps.executeUpdate());
 						}
 						int[] rowsAffectedArray = new int[rowsAffected.size()];
 						for (int i = 0; i < rowsAffectedArray.lengthi++) {
 							rowsAffectedArray[i] = rowsAffected.get(i);
 						}
 						return rowsAffectedArray;
 					}
 				}
 				finally {
 					if (pss instanceof ParameterDisposer) {
 					}
 				}
 			}
 		});
 	}
 
 
 	//-------------------------------------------------------------------------
 	// Methods dealing with callable statements
 	//-------------------------------------------------------------------------
 
 	public <T> T execute(CallableStatementCreator cscCallableStatementCallback<T> action)
 
 		Assert.notNull(csc"CallableStatementCreator must not be null");
 		Assert.notNull(action"Callback object must not be null");
 			String sql = getSql(csc);
 			.debug("Calling stored procedure" + (sql != null ? " [" + sql  + "]" : ""));
 		}
 
 		Connection con = DataSourceUtils.getConnection(getDataSource());
 		CallableStatement cs = null;
 		try {
 			Connection conToUse = con;
 			if (this. != null) {
 				conToUse = this..getNativeConnection(con);
 			}
 			cs = csc.createCallableStatement(conToUse);
 			CallableStatement csToUse = cs;
 			if (this. != null) {
 			}
 			T result = action.doInCallableStatement(csToUse);
 			return result;
 		}
 		catch (SQLException ex) {
 			// Release Connection early, to avoid potential connection pool deadlock
 			// in the case when the exception translator hasn't been initialized yet.
 			if (csc instanceof ParameterDisposer) {
 			}
 			String sql = getSql(csc);
 			csc = null;
 			JdbcUtils.closeStatement(cs);
 			cs = null;
 			DataSourceUtils.releaseConnection(congetDataSource());
 			con = null;
 			throw getExceptionTranslator().translate("CallableStatementCallback"sqlex);
 		}
 		finally {
 			if (csc instanceof ParameterDisposer) {
 			}
 			JdbcUtils.closeStatement(cs);
 			DataSourceUtils.releaseConnection(congetDataSource());
 		}
 	}
 
 	public <T> T execute(String callStringCallableStatementCallback<T> actionthrows DataAccessException {
 		return execute(new SimpleCallableStatementCreator(callString), action);
 	}
 
 	public Map<StringObjectcall(CallableStatementCreator cscList<SqlParameterdeclaredParameters)
 
 		final List<SqlParameterupdateCountParameters = new ArrayList<SqlParameter>();
 		final List<SqlParameterresultSetParameters = new ArrayList<SqlParameter>();
 		final List<SqlParametercallParameters = new ArrayList<SqlParameter>();
 		for (SqlParameter parameter : declaredParameters) {
 			if (parameter.isResultsParameter()) {
 				if (parameter instanceof SqlReturnResultSet) {
 					resultSetParameters.add(parameter);
 				}
 				else {
 					updateCountParameters.add(parameter);					
 				}
 			}
 			else {
				callParameters.add(parameter);
				boolean retVal = cs.execute();
				int updateCount = cs.getUpdateCount();
					.debug("CallableStatement.execute() returned '" + retVal + "'");
					.debug("CallableStatement.getUpdateCount() returned " + updateCount);
				Map<StringObjectreturnedResults = createResultsMap();
				if (retVal || updateCount != -1) {
					returnedResults.putAll(extractReturnedResults(csupdateCountParametersresultSetParametersupdateCount));
				returnedResults.putAll(extractOutputParameters(cscallParameters));
				return returnedResults;
		});
	}

Extract returned ResultSets from the completed stored procedure.

Parameters:
cs JDBC wrapper for the stored procedure
updateCountParameters Parameter list of declared update count parameters for the stored procedure
resultSetParameters Parameter list of declared resturn resultSet parameters for the stored procedure
Returns:
Map that contains returned results
			CallableStatement csList updateCountParametersList resultSetParametersint updateCount)
			throws SQLException {
		Map<StringObjectreturnedResults = new HashMap<StringObject>();
		int rsIndex = 0;
		int updateIndex = 0;
		boolean moreResults;
			do {
				if (updateCount == -1) {
					if (resultSetParameters != null && resultSetParameters.size() > rsIndex) {
						SqlReturnResultSet declaredRsParam = (SqlReturnResultSet)resultSetParameters.get(rsIndex);
						returnedResults.putAll(processResultSet(cs.getResultSet(), declaredRsParam));
						rsIndex++;
					else {
							String rsName =  + (rsIndex + 1);
							SqlReturnResultSet undeclaredRsParam = new SqlReturnResultSet(rsNamenew ColumnMapRowMapper());
							.info("Added default SqlReturnResultSet parameter named " + rsName);
							returnedResults.putAll(processResultSet(cs.getResultSet(), undeclaredRsParam));
							rsIndex++;
				else {
					if (updateCountParameters != null && updateCountParameters.size() > updateIndex) {
						SqlReturnUpdateCount ucParam = (SqlReturnUpdateCount)updateCountParameters.get(updateIndex);
						String declaredUcName = ucParam.getName();
						returnedResults.put(declaredUcNameupdateCount);
						updateIndex++;
					else {
							String undeclaredUcName =  + (updateIndex + 1);
							.info("Added default SqlReturnUpdateCount parameter named " + undeclaredUcName);
							returnedResults.put(undeclaredUcNameupdateCount);
							updateIndex++;
				moreResults = cs.getMoreResults();
				updateCount = cs.getUpdateCount();
					.debug("CallableStatement.getUpdateCount() returned " + updateCount);
			while (moreResults || updateCount != -1);
		return returnedResults;
	}

Extract output parameters from the completed stored procedure.

Parameters:
cs JDBC wrapper for the stored procedure
parameters parameter list for the stored procedure
Returns:
Map that contains returned results
			throws SQLException {
		Map<StringObjectreturnedResults = new HashMap<StringObject>();
		int sqlColIndex = 1;
		for (SqlParameter param : parameters) {
			if (param instanceof SqlOutParameter) {
				SqlOutParameter outParam = (SqlOutParameterparam;
				if (outParam.isReturnTypeSupported()) {
							cssqlColIndexoutParam.getSqlType(), outParam.getTypeName());
					returnedResults.put(outParam.getName(), out);
				else {
					Object out = cs.getObject(sqlColIndex);
					if (out instanceof ResultSet) {
						if (outParam.isResultSetSupported()) {
							returnedResults.putAll(processResultSet((ResultSetoutoutParam));
						else {
							String rsName = outParam.getName();
							SqlReturnResultSet rsParam = new SqlReturnResultSet(rsNamenew ColumnMapRowMapper());
							returnedResults.putAll(processResultSet(cs.getResultSet(), rsParam));
							.info("Added default SqlReturnResultSet parameter named " + rsName);
					else {
						returnedResults.put(outParam.getName(), out);
			if (!(param.isResultsParameter())) {
				sqlColIndex++;
		return returnedResults;
	}

Process the given ResultSet from a stored procedure.

Parameters:
rs the ResultSet to process
param the corresponding stored procedure parameter
Returns:
Map that contains returned results
	@SuppressWarnings("unchecked")
		if (rs == null) {
			return Collections.emptyMap();
		Map<StringObjectreturnedResults = new HashMap<StringObject>();
		try {
			ResultSet rsToUse = rs;
			if (this. != null) {
				rsToUse = this.