Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2002-2014 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.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.BatchUpdateException;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.jdbc.SQLWarningException;
import org.springframework.jdbc.datasource.ConnectionProxy;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.support.JdbcAccessor;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.util.Assert;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.util.StringUtils;
/**
* 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
* {@code org.springframework.dao} package.
*
*
Code using this class need only implement callback interfaces, giving
* them a clearly defined contract. The {@link PreparedStatementCreator} callback
* interface creates a prepared statement given a Connection, providing SQL and
* any necessary parameters. The {@link ResultSetExtractor} interface extracts
* values from a ResultSet. See also {@link PreparedStatementSetter} and
* {@link 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 {@link 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.
*
*
NOTE: An instance of this class is thread-safe once configured.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Thomas Risberg
* @since May 3, 2001
* @see PreparedStatementCreator
* @see PreparedStatementSetter
* @see CallableStatementCreator
* @see PreparedStatementCallback
* @see CallableStatementCallback
* @see ResultSetExtractor
* @see RowCallbackHandler
* @see RowMapper
* @see org.springframework.jdbc.support.SQLExceptionTranslator
*/
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 */
private NativeJdbcExtractor 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 processing will be take place unless the variable
* {@code skipResultsProcessing} is set to {@code 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.
* @see #setDataSource
*/
public JdbcTemplate() {
}
/**
* Construct a new JdbcTemplate, given a DataSource to obtain connections from.
*
Note: This will not trigger initialization of the exception translator.
* @param dataSource the JDBC DataSource to obtain connections from
*/
public JdbcTemplate(DataSource dataSource) {
setDataSource(dataSource);
afterPropertiesSet();
}
/**
* 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.
* @param dataSource the JDBC DataSource to obtain connections from
* @param lazyInit whether to lazily initialize the SQLExceptionTranslator
*/
public JdbcTemplate(DataSource dataSource, boolean lazyInit) {
setDataSource(dataSource);
setLazyInit(lazyInit);
afterPropertiesSet();
}
/**
* 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.nativeJdbcExtractor = extractor;
}
/**
* Return the current NativeJdbcExtractor implementation.
*/
public NativeJdbcExtractor getNativeJdbcExtractor() {
return this.nativeJdbcExtractor;
}
/**
* 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.
* @see java.sql.SQLWarning
* @see org.springframework.jdbc.SQLWarningException
* @see #handleWarnings
*/
public void setIgnoreWarnings(boolean ignoreWarnings) {
this.ignoreWarnings = ignoreWarnings;
}
/**
* Return whether or not we ignore SQLWarnings.
*/
public boolean isIgnoreWarnings() {
return this.ignoreWarnings;
}
/**
* 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.
* @see java.sql.Statement#setFetchSize
*/
public void setFetchSize(int fetchSize) {
this.fetchSize = fetchSize;
}
/**
* Return the fetch size specified for this JdbcTemplate.
*/
public int getFetchSize() {
return this.fetchSize;
}
/**
* 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.
* @see java.sql.Statement#setMaxRows
*/
public void setMaxRows(int maxRows) {
this.maxRows = maxRows;
}
/**
* Return the maximum number of rows specified for this JdbcTemplate.
*/
public int getMaxRows() {
return this.maxRows;
}
/**
* 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.
* @see java.sql.Statement#setQueryTimeout
*/
public void setQueryTimeout(int queryTimeout) {
this.queryTimeout = queryTimeout;
}
/**
* Return the query timeout for statements that this JdbcTemplate executes.
*/
public int getQueryTimeout() {
return this.queryTimeout;
}
/**
* 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 = skipResultsProcessing;
}
/**
* Return whether results processing should be skipped.
*/
public boolean isSkipResultsProcessing() {
return this.skipResultsProcessing;
}
/**
* Set whether undeclared results should be skipped.
*/
public void setSkipUndeclaredResults(boolean skipUndeclaredResults) {
this.skipUndeclaredResults = skipUndeclaredResults;
}
/**
* Return whether undeclared results should be skipped.
*/
public boolean isSkipUndeclaredResults() {
return this.skipUndeclaredResults;
}
/**
* 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 = 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() {
return this.resultsMapCaseInsensitive;
}
//-------------------------------------------------------------------------
// Methods dealing with a plain java.sql.Connection
//-------------------------------------------------------------------------
@Override
public T execute(ConnectionCallback action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(getDataSource());
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null) {
// Extract native JDBC Connection, castable to OracleConnection or the like.
conToUse = this.nativeJdbcExtractor.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(con, getDataSource());
con = null;
throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
}
finally {
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
/**
* Create a close-suppressing proxy for the given JDBC Connection.
* Called by the {@code execute} method.
*
The proxy also prepares returned JDBC Statements, applying
* statement settings such as fetch size, max rows, and query timeout.
* @param con the JDBC Connection to create a proxy for
* @return the Connection proxy
* @see java.sql.Connection#close()
* @see #execute(ConnectionCallback)
* @see #applyStatementSettings
*/
protected Connection createConnectionProxy(Connection con) {
return (Connection) Proxy.newProxyInstance(
ConnectionProxy.class.getClassLoader(),
new Class[] {ConnectionProxy.class},
new CloseSuppressingInvocationHandler(con));
}
//-------------------------------------------------------------------------
// Methods dealing with static SQL (java.sql.Statement)
//-------------------------------------------------------------------------
@Override
public T execute(StatementCallback action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(getDataSource());
Statement stmt = null;
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null &&
this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
stmt = conToUse.createStatement();
applyStatementSettings(stmt);
Statement stmtToUse = stmt;
if (this.nativeJdbcExtractor != null) {
stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
}
T result = action.doInStatement(stmtToUse);
handleWarnings(stmt);
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(con, getDataSource());
con = null;
throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
}
finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
@Override
public void execute(final String sql) throws DataAccessException {
if (logger.isDebugEnabled()) {
logger.debug("Executing SQL statement [" + sql + "]");
}
class ExecuteStatementCallback implements StatementCallback