18.Spring的數(shù)據(jù)訪問

1.數(shù)據(jù)訪問對象DAO或者Repository組件
為了避免持久化的邏輯分散到應(yīng)用中的各個組件中,最好是將數(shù)據(jù)訪問的功能放到一個或者多個專注于此項任務(wù)的組件之中,這樣的組件叫做數(shù)據(jù)訪問對象或者Repository。
2.Spring的數(shù)據(jù)訪問異常體系
(1)了解導(dǎo)致SQLException發(fā)生的異常
a.應(yīng)用程序無法連接數(shù)據(jù)庫
b.要執(zhí)行的查詢存在語法錯誤
c.查詢中所使用的表或者列不存在
d.試圖插入或者更新數(shù)據(jù)違反數(shù)據(jù)庫約束的數(shù)據(jù)裆赵。
SQLException被當(dāng)做處理數(shù)據(jù)訪問所有問題的通用異常战授。對于所有的數(shù)據(jù)訪問問題都會拋出SQLException異常,而不是對每種可能的問題都會有不同的異常類型植兰。
(2)DataAccessException
Spring中的異常都是繼承自DataAccessException份帐,它是一個非檢查型異常。


回想一下我們在用JDBC的時候毡咏,需要寫好多重復(fù)的代碼,比如創(chuàng)建連接恢总,打開數(shù)據(jù)庫連接迎罗,然后執(zhí)行完SQL以后,還要捕獲異常片仿,關(guān)閉連接等纹安,其中所不同的就是執(zhí)行的SQL有所不同,其余的基本一樣,此處我們可以使用設(shè)計模式中的模板方法钻蔑,來將那些共通重復(fù)的代碼進(jìn)行抽取,建立一個模板奸鸯,所改變的就是這個模板中的SQL咪笑。
模板方法就是將過程中與特定實現(xiàn)相關(guān)的部分委托給接口,而這個接口的不同實現(xiàn)定義了過程中的具體行為娄涩。
Spring將數(shù)據(jù)訪問過程中固定的和可變的部分劃分為兩種:模板和回調(diào)窗怒。
(1)模板:管理過程中固定的部分。
(2)回調(diào):處理自定義的數(shù)據(jù)訪問代碼蓄拣。
Spring的模板類處理數(shù)據(jù)訪問的固定部分(事務(wù)控制扬虚,管理資源以及處理異常);應(yīng)用程序相關(guān)的數(shù)據(jù)訪問(語句球恤,綁定參數(shù)以及整理結(jié)果集在回調(diào)中實現(xiàn)處理)


Spring提供的數(shù)據(jù)訪問模板.jpg

3.配置數(shù)據(jù)源
(1)Spring提供了上下文中配置數(shù)據(jù)源bean的多種方式:
a.通過JDBC驅(qū)動程序定義的數(shù)據(jù)源
b.通過JNDI查找的數(shù)據(jù)源
c.連接池的數(shù)據(jù)源
(2)JNDI數(shù)據(jù)源
a.優(yōu)點
使用JNDI數(shù)據(jù)源辜昵,好處在于數(shù)據(jù)源完全可以在應(yīng)用程序之外進(jìn)行管理,這樣應(yīng)用程序只需要在訪問數(shù)據(jù)庫的時候查找數(shù)據(jù)源就可以咽斧。在應(yīng)用服務(wù)器中管理的數(shù)據(jù)源通常以池的方式組織堪置,從而具備良好的性能,并且還支持系統(tǒng)管理員對其進(jìn)行切換张惹。
b.在XML中配置
使用jee命名空間下的<jee:jndi-lookup>元素來檢索JNDI中的任何對象并將其作為Spring的Bean。jndi-name屬性就是制定JNDI資源的名稱坎匿。resource-ref設(shè)置為true雷激,這樣給定的jndi-name將會自動添加java:comp/env的前綴。
c.使用Java進(jìn)行配置Bean

  JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
  jndiObjectFactoryBean.setJndiName("jdbc/jkgl");
  jndiObjectFactoryBean.setResourceRef(true);
      jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);

(3)嵌入式的數(shù)據(jù)源
嵌入式數(shù)據(jù)庫是應(yīng)用的一部分进栽,不是應(yīng)用連接的獨立數(shù)據(jù)庫服務(wù)器。
a.在XML中配置數(shù)據(jù)源恭垦,可以使用jdbc命名空間唠帝。

<jdbc:embeded-database><!-我們可以配置多個或者不配置<jdbc:script>->

(4)使用profile作為數(shù)據(jù)源
Spring提供了profile襟衰,需要做的就是將每個數(shù)據(jù)源配置在不同的profile中绍坝,通過使用profile功能,會在運行時選擇數(shù)據(jù)源把介,這取決于哪一個profile處于激活狀態(tài)。
a.Java配置

@Profile注解

b.XML配置

<beans profile="name"></beans>

4.數(shù)據(jù)源連接池
在配置數(shù)據(jù)源的時候向臀,我們也可以選擇數(shù)據(jù)源連接池砂缩,有好多開源的,比如:
(1)Apache Commons DBCP
(2)C3P0
(3)BoneCP
這些連接池中的大多數(shù)能配置為Spring數(shù)據(jù)源双吆,在一定程度上與Spring自帶的DriverManagerDataSource或者SingleConnectionDataSource很類似。

package org.springframework.jdbc.datasource;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

public class DriverManagerDataSource extends AbstractDriverBasedDataSource {
    public DriverManagerDataSource() {
    }

    public DriverManagerDataSource(String url) {
        this.setUrl(url);
    }

    public DriverManagerDataSource(String url, String username, String password) {
        this.setUrl(url);
        this.setUsername(username);
        this.setPassword(password);
    }

    public DriverManagerDataSource(String url, Properties conProps) {
        this.setUrl(url);
        this.setConnectionProperties(conProps);
    }

    public void setDriverClassName(String driverClassName) {
        Assert.hasText(driverClassName, "Property 'driverClassName' must not be empty");
        String driverClassNameToUse = driverClassName.trim();

        try {
            Class.forName(driverClassNameToUse, true, ClassUtils.getDefaultClassLoader());
        } catch (ClassNotFoundException var4) {
            throw new IllegalStateException("Could not load JDBC driver class [" + driverClassNameToUse + "]", var4);
        }

        if(this.logger.isInfoEnabled()) {
            this.logger.info("Loaded JDBC driver: " + driverClassNameToUse);
        }

    }

    protected Connection getConnectionFromDriver(Properties props) throws SQLException {
        String url = this.getUrl();
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Creating new JDBC DriverManager Connection to [" + url + "]");
        }

        return this.getConnectionFromDriverManager(url, props);
    }

    protected Connection getConnectionFromDriverManager(String url, Properties props) throws SQLException {
        return DriverManager.getConnection(url, props);
    }
}

(4)org.springframework.jdbc.datasource包
a.DriverManagerDataSource在每個連接請求時都會返回一個新建的連接临庇,與DBCP的BasicDataSource不同的是淮蜈,由DriverManagerDataSource提供的連接并沒有進(jìn)行池化管理梧田。
b.SimpleDriverDataSource與DriverManagerDataSource的工作方式類似鹉梨,但是他直接使用JDBC的驅(qū)動,來解決在特定環(huán)境下的類加載問題泡仗,這樣的環(huán)境包括OSGi容器搔课。
c.SingleConnectionDataSouce在每個連接請求時都會返回同一個的連接∨鄯龋可以將其視為只有一個連接的池。
5.Spring中的JDBC模板
因為在JDBC中嗅剖,我們會重復(fù)的寫創(chuàng)建連接關(guān)閉資源等語句,Spring為我們提供了JDBC模板,它主要管理資源和異常處理欺旧,從而簡化代碼,讓我們只需要編寫從數(shù)據(jù)庫讀寫數(shù)據(jù)的必須代碼留拾。
(1)Spring提供的JDBC模板:
a.JdbcTemplate
最基本的Spring JDBC模板,這個模板支持簡單的JDBC數(shù)據(jù)庫訪問功能以及基于索引參數(shù)的查詢咳蔚。
b.NamedParameterJdbcTemplate
使用該模板類來執(zhí)行查詢時可以將值以命名參數(shù)的形式綁定到SQL中,不是使用簡單的索引參數(shù)。
(2)JdbcTemplate源碼

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.Iterator;
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;

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-";
    private NativeJdbcExtractor nativeJdbcExtractor;
    private boolean ignoreWarnings = true;
    private int fetchSize = -1;
    private int maxRows = -1;
    private int queryTimeout = -1;
    private boolean skipResultsProcessing = false;
    private boolean skipUndeclaredResults = false;
    private boolean resultsMapCaseInsensitive = false;

    public JdbcTemplate() {
    }
    /**
      *構(gòu)造方法扭粱,注入一個DataSource作為參數(shù)
      */
    public JdbcTemplate(DataSource dataSource) {
        this.setDataSource(dataSource);
        this.afterPropertiesSet();
    }

    public JdbcTemplate(DataSource dataSource, boolean lazyInit) {
        this.setDataSource(dataSource);
        this.setLazyInit(lazyInit);
        this.afterPropertiesSet();
    }

    public void setNativeJdbcExtractor(NativeJdbcExtractor extractor) {
        this.nativeJdbcExtractor = extractor;
    }

    public NativeJdbcExtractor getNativeJdbcExtractor() {
        return this.nativeJdbcExtractor;
    }

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

    public boolean isIgnoreWarnings() {
        return this.ignoreWarnings;
    }

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

    public int getFetchSize() {
        return this.fetchSize;
    }

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

    public int getMaxRows() {
        return this.maxRows;
    }

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

    public int getQueryTimeout() {
        return this.queryTimeout;
    }

    public void setSkipResultsProcessing(boolean skipResultsProcessing) {
        this.skipResultsProcessing = skipResultsProcessing;
    }

    public boolean isSkipResultsProcessing() {
        return this.skipResultsProcessing;
    }

    public void setSkipUndeclaredResults(boolean skipUndeclaredResults) {
        this.skipUndeclaredResults = skipUndeclaredResults;
    }

    public boolean isSkipUndeclaredResults() {
        return this.skipUndeclaredResults;
    }

    public void setResultsMapCaseInsensitive(boolean resultsMapCaseInsensitive) {
        this.resultsMapCaseInsensitive = resultsMapCaseInsensitive;
    }

    public boolean isResultsMapCaseInsensitive() {
        return this.resultsMapCaseInsensitive;
    }
 
    public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");
        Connection con = DataSourceUtils.getConnection(this.getDataSource());

        Object var4;
        try {
            Connection conToUse;
            if(this.nativeJdbcExtractor != null) {
                conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
            } else {
                conToUse = this.createConnectionProxy(con);
            }

            var4 = action.doInConnection(conToUse);
        } catch (SQLException var8) {
            DataSourceUtils.releaseConnection(con, this.getDataSource());
            con = null;
            throw this.getExceptionTranslator().translate("ConnectionCallback", getSql(action), var8);
        } finally {
            DataSourceUtils.releaseConnection(con, this.getDataSource());
        }

        return var4;
    }

    protected Connection createConnectionProxy(Connection con) {
        return (Connection)Proxy.newProxyInstance(ConnectionProxy.class.getClassLoader(), new Class[]{ConnectionProxy.class}, new JdbcTemplate.CloseSuppressingInvocationHandler(con));
    }

    public <T> T execute(StatementCallback<T> action) throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");
        Connection con = DataSourceUtils.getConnection(this.getDataSource());
        Statement stmt = null;

        Object var7;
        try {
            Connection conToUse = con;
            if(this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
                conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
            }

            stmt = conToUse.createStatement();
            this.applyStatementSettings(stmt);
            Statement stmtToUse = stmt;
            if(this.nativeJdbcExtractor != null) {
                stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
            }

            T result = action.doInStatement(stmtToUse);
            this.handleWarnings(stmt);
            var7 = result;
        } catch (SQLException var11) {
            JdbcUtils.closeStatement(stmt);
            stmt = null;
            DataSourceUtils.releaseConnection(con, this.getDataSource());
            con = null;
            throw this.getExceptionTranslator().translate("StatementCallback", getSql(action), var11);
        } finally {
            JdbcUtils.closeStatement(stmt);
            DataSourceUtils.releaseConnection(con, this.getDataSource());
        }

        return var7;
    }

    public void execute(final String sql) throws DataAccessException {
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Executing SQL statement [" + sql + "]");
        }

        class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
            ExecuteStatementCallback() {
            }

            public Object doInStatement(Statement stmt) throws SQLException {
                stmt.execute(sql);
                return null;
            }

            public String getSql() {
                return sql;
            }
        }

        this.execute((StatementCallback)(new ExecuteStatementCallback()));
    }

    public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
        Assert.notNull(sql, "SQL must not be null");
        Assert.notNull(rse, "ResultSetExtractor must not be null");
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Executing SQL query [" + sql + "]");
        }

        class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
            QueryStatementCallback() {
            }

            public T doInStatement(Statement stmt) throws SQLException {
                ResultSet rs = null;

                Object var4;
                try {
                    rs = stmt.executeQuery(sql);
                    ResultSet rsToUse = rs;
                    if(JdbcTemplate.this.nativeJdbcExtractor != null) {
                        rsToUse = JdbcTemplate.this.nativeJdbcExtractor.getNativeResultSet(rs);
                    }

                    var4 = rse.extractData(rsToUse);
                } finally {
                    JdbcUtils.closeResultSet(rs);
                }

                return var4;
            }

            public String getSql() {
                return sql;
            }
        }

        return this.execute((StatementCallback)(new QueryStatementCallback()));
    }

    public void query(String sql, RowCallbackHandler rch) throws DataAccessException {
        this.query((String)sql, (ResultSetExtractor)(new JdbcTemplate.RowCallbackHandlerResultSetExtractor(rch)));
    }

    public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException {
        return (List)this.query((String)sql, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper)));
    }

    public Map<String, Object> queryForMap(String sql) throws DataAccessException {
        return (Map)this.queryForObject(sql, this.getColumnMapRowMapper());
    }

    public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws DataAccessException {
        List<T> results = this.query(sql, rowMapper);
        return DataAccessUtils.requiredSingleResult(results);
    }

    public <T> T queryForObject(String sql, Class<T> requiredType) throws DataAccessException {
        return this.queryForObject(sql, this.getSingleColumnRowMapper(requiredType));
    }

    /** @deprecated */
    @Deprecated
    public long queryForLong(String sql) throws DataAccessException {
        Number number = (Number)this.queryForObject(sql, Long.class);
        return number != null?number.longValue():0L;
    }

    public <T> List<T> queryForList(String sql, Class<T> elementType) throws DataAccessException {
        return this.query(sql, this.getSingleColumnRowMapper(elementType));
    }

    public List<Map<String, Object>> queryForList(String sql) throws DataAccessException {
        return this.query(sql, this.getColumnMapRowMapper());
    }

    public SqlRowSet queryForRowSet(String sql) throws DataAccessException {
        return (SqlRowSet)this.query((String)sql, (ResultSetExtractor)(new SqlRowSetResultSetExtractor()));
    }

    public int update(final String sql) throws DataAccessException {
        Assert.notNull(sql, "SQL must not be null");
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Executing SQL update [" + sql + "]");
        }

        class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider {
            UpdateStatementCallback() {
            }

            public Integer doInStatement(Statement stmt) throws SQLException {
                int rows = stmt.executeUpdate(sql);
                if(JdbcTemplate.this.logger.isDebugEnabled()) {
                    JdbcTemplate.this.logger.debug("SQL update affected " + rows + " rows");
                }

                return Integer.valueOf(rows);
            }

            public String getSql() {
                return sql;
            }
        }

        return ((Integer)this.execute((StatementCallback)(new UpdateStatementCallback()))).intValue();
    }

    public int[] batchUpdate(final String... sql) throws DataAccessException {
        Assert.notEmpty(sql, "SQL array must not be empty");
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Executing SQL batch update of " + sql.length + " statements");
        }

        class BatchUpdateStatementCallback implements StatementCallback<int[]>, SqlProvider {
            private String currSql;

            BatchUpdateStatementCallback() {
            }

            public int[] doInStatement(Statement stmt) throws SQLException, DataAccessException {
                int[] rowsAffected = new int[sql.length];
                if(JdbcUtils.supportsBatchUpdates(stmt.getConnection())) {
                    String[] var3 = sql;
                    int var4 = var3.length;

                    int ix;
                    for(ix = 0; ix < var4; ++ix) {
                        String sqlStmt = var3[ix];
                        this.currSql = this.appendSql(this.currSql, sqlStmt);
                        stmt.addBatch(sqlStmt);
                    }

                    try {
                        rowsAffected = stmt.executeBatch();
                    } catch (BatchUpdateException var7) {
                        BatchUpdateException ex = var7;
                        String batchExceptionSql = null;

                        for(ix = 0; ix < ex.getUpdateCounts().length; ++ix) {
                            if(ex.getUpdateCounts()[ix] == -3) {
                                batchExceptionSql = this.appendSql(batchExceptionSql, sql[ix]);
                            }
                        }

                        if(StringUtils.hasLength(batchExceptionSql)) {
                            this.currSql = batchExceptionSql;
                        }

                        throw ex;
                    }
                } else {
                    for(int i = 0; i < sql.length; ++i) {
                        this.currSql = sql[i];
                        if(stmt.execute(sql[i])) {
                            throw new InvalidDataAccessApiUsageException("Invalid batch SQL statement: " + sql[i]);
                        }

                        rowsAffected[i] = stmt.getUpdateCount();
                    }
                }

                return rowsAffected;
            }

            private String appendSql(String sqlx, String statement) {
                return StringUtils.isEmpty(sqlx)?statement:sqlx + "; " + statement;
            }

            public String getSql() {
                return this.currSql;
            }
        }

        return (int[])this.execute((StatementCallback)(new BatchUpdateStatementCallback()));
    }

    public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action) throws DataAccessException {
        Assert.notNull(psc, "PreparedStatementCreator must not be null");
        Assert.notNull(action, "Callback object must not be null");
        if(this.logger.isDebugEnabled()) {
            String sql = getSql(psc);
            this.logger.debug("Executing prepared SQL statement" + (sql != null?" [" + sql + "]":""));
        }

        Connection con = DataSourceUtils.getConnection(this.getDataSource());
        PreparedStatement ps = null;

        Object var8;
        try {
            Connection conToUse = con;
            if(this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) {
                conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
            }

            ps = psc.createPreparedStatement(conToUse);
            this.applyStatementSettings(ps);
            PreparedStatement psToUse = ps;
            if(this.nativeJdbcExtractor != null) {
                psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps);
            }

            T result = action.doInPreparedStatement(psToUse);
            this.handleWarnings((Statement)ps);
            var8 = result;
        } catch (SQLException var12) {
            if(psc instanceof ParameterDisposer) {
                ((ParameterDisposer)psc).cleanupParameters();
            }

            String sql = getSql(psc);
            psc = null;
            JdbcUtils.closeStatement(ps);
            ps = null;
            DataSourceUtils.releaseConnection(con, this.getDataSource());
            con = null;
            throw this.getExceptionTranslator().translate("PreparedStatementCallback", sql, var12);
        } finally {
            if(psc instanceof ParameterDisposer) {
                ((ParameterDisposer)psc).cleanupParameters();
            }

            JdbcUtils.closeStatement(ps);
            DataSourceUtils.releaseConnection(con, this.getDataSource());
        }

        return var8;
    }

    public <T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException {
        return this.execute((PreparedStatementCreator)(new JdbcTemplate.SimplePreparedStatementCreator(sql)), (PreparedStatementCallback)action);
    }

    public <T> T query(PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor<T> rse) throws DataAccessException {
        Assert.notNull(rse, "ResultSetExtractor must not be null");
        this.logger.debug("Executing prepared SQL query");
        return this.execute(psc, new PreparedStatementCallback<T>() {
            public T doInPreparedStatement(PreparedStatement ps) throws SQLException {
                ResultSet rs = null;

                Object var4;
                try {
                    if(pss != null) {
                        pss.setValues(ps);
                    }

                    rs = ps.executeQuery();
                    ResultSet rsToUse = rs;
                    if(JdbcTemplate.this.nativeJdbcExtractor != null) {
                        rsToUse = JdbcTemplate.this.nativeJdbcExtractor.getNativeResultSet(rs);
                    }

                    var4 = rse.extractData(rsToUse);
                } finally {
                    JdbcUtils.closeResultSet(rs);
                    if(pss instanceof ParameterDisposer) {
                        ((ParameterDisposer)pss).cleanupParameters();
                    }

                }

                return var4;
            }
        });
    }

    public <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse) throws DataAccessException {
        return this.query((PreparedStatementCreator)psc, (PreparedStatementSetter)null, (ResultSetExtractor)rse);
    }

    public <T> T query(String sql, PreparedStatementSetter pss, ResultSetExtractor<T> rse) throws DataAccessException {
        return this.query((PreparedStatementCreator)(new JdbcTemplate.SimplePreparedStatementCreator(sql)), (PreparedStatementSetter)pss, (ResultSetExtractor)rse);
    }

    public <T> T query(String sql, Object[] args, int[] argTypes, ResultSetExtractor<T> rse) throws DataAccessException {
        return this.query(sql, this.newArgTypePreparedStatementSetter(args, argTypes), rse);
    }

    public <T> T query(String sql, Object[] args, ResultSetExtractor<T> rse) throws DataAccessException {
        return this.query(sql, this.newArgPreparedStatementSetter(args), rse);
    }

    public <T> T query(String sql, ResultSetExtractor<T> rse, Object... args) throws DataAccessException {
        return this.query(sql, this.newArgPreparedStatementSetter(args), rse);
    }

    public void query(PreparedStatementCreator psc, RowCallbackHandler rch) throws DataAccessException {
        this.query((PreparedStatementCreator)psc, (ResultSetExtractor)(new JdbcTemplate.RowCallbackHandlerResultSetExtractor(rch)));
    }

    public void query(String sql, PreparedStatementSetter pss, RowCallbackHandler rch) throws DataAccessException {
        this.query((String)sql, (PreparedStatementSetter)pss, (ResultSetExtractor)(new JdbcTemplate.RowCallbackHandlerResultSetExtractor(rch)));
    }

    public void query(String sql, Object[] args, int[] argTypes, RowCallbackHandler rch) throws DataAccessException {
        this.query(sql, this.newArgTypePreparedStatementSetter(args, argTypes), rch);
    }

    public void query(String sql, Object[] args, RowCallbackHandler rch) throws DataAccessException {
        this.query(sql, this.newArgPreparedStatementSetter(args), rch);
    }

    public void query(String sql, RowCallbackHandler rch, Object... args) throws DataAccessException {
        this.query(sql, this.newArgPreparedStatementSetter(args), rch);
    }

    public <T> List<T> query(PreparedStatementCreator psc, RowMapper<T> rowMapper) throws DataAccessException {
        return (List)this.query((PreparedStatementCreator)psc, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper)));
    }

    public <T> List<T> query(String sql, PreparedStatementSetter pss, RowMapper<T> rowMapper) throws DataAccessException {
        return (List)this.query((String)sql, (PreparedStatementSetter)pss, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper)));
    }

    public <T> List<T> query(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper) throws DataAccessException {
        return (List)this.query(sql, args, argTypes, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper)));
    }

    public <T> List<T> query(String sql, Object[] args, RowMapper<T> rowMapper) throws DataAccessException {
        return (List)this.query((String)sql, (Object[])args, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper)));
    }

    public <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException {
        return (List)this.query((String)sql, (Object[])args, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper)));
    }

    public <T> T queryForObject(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper) throws DataAccessException {
        List<T> results = (List)this.query(sql, args, argTypes, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper, 1)));
        return DataAccessUtils.requiredSingleResult(results);
    }

    public <T> T queryForObject(String sql, Object[] args, RowMapper<T> rowMapper) throws DataAccessException {
        List<T> results = (List)this.query((String)sql, (Object[])args, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper, 1)));
        return DataAccessUtils.requiredSingleResult(results);
    }

    public <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException {
        List<T> results = (List)this.query((String)sql, (Object[])args, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper, 1)));
        return DataAccessUtils.requiredSingleResult(results);
    }

    public <T> T queryForObject(String sql, Object[] args, int[] argTypes, Class<T> requiredType) throws DataAccessException {
        return this.queryForObject(sql, args, argTypes, this.getSingleColumnRowMapper(requiredType));
    }

    public <T> T queryForObject(String sql, Object[] args, Class<T> requiredType) throws DataAccessException {
        return this.queryForObject(sql, args, this.getSingleColumnRowMapper(requiredType));
    }

    public <T> T queryForObject(String sql, Class<T> requiredType, Object... args) throws DataAccessException {
        return this.queryForObject(sql, args, this.getSingleColumnRowMapper(requiredType));
    }

    public Map<String, Object> queryForMap(String sql, Object[] args, int[] argTypes) throws DataAccessException {
        return (Map)this.queryForObject(sql, args, argTypes, this.getColumnMapRowMapper());
    }

    public Map<String, Object> queryForMap(String sql, Object... args) throws DataAccessException {
        return (Map)this.queryForObject(sql, args, this.getColumnMapRowMapper());
    }




    public <T> List<T> queryForList(String sql, Object[] args, int[] argTypes, Class<T> elementType) throws DataAccessException {
        return this.query(sql, args, argTypes, this.getSingleColumnRowMapper(elementType));
    }

    public <T> List<T> queryForList(String sql, Object[] args, Class<T> elementType) throws DataAccessException {
        return this.query(sql, args, this.getSingleColumnRowMapper(elementType));
    }

    public <T> List<T> queryForList(String sql, Class<T> elementType, Object... args) throws DataAccessException {
        return this.query(sql, args, this.getSingleColumnRowMapper(elementType));
    }

    public List<Map<String, Object>> queryForList(String sql, Object[] args, int[] argTypes) throws DataAccessException {
        return this.query(sql, args, argTypes, this.getColumnMapRowMapper());
    }

    public List<Map<String, Object>> queryForList(String sql, Object... args) throws DataAccessException {
        return this.query(sql, args, this.getColumnMapRowMapper());
    }

    public SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes) throws DataAccessException {
        return (SqlRowSet)this.query(sql, args, argTypes, (ResultSetExtractor)(new SqlRowSetResultSetExtractor()));
    }

    public SqlRowSet queryForRowSet(String sql, Object... args) throws DataAccessException {
        return (SqlRowSet)this.query((String)sql, (Object[])args, (ResultSetExtractor)(new SqlRowSetResultSetExtractor()));
    }

    protected int update(PreparedStatementCreator psc, final PreparedStatementSetter pss) throws DataAccessException {
        this.logger.debug("Executing prepared SQL update");
        return ((Integer)this.execute(psc, new PreparedStatementCallback<Integer>() {
            public Integer doInPreparedStatement(PreparedStatement ps) throws SQLException {
                Integer var3;
                try {
                    if(pss != null) {
                        pss.setValues(ps);
                    }

                    int rows = ps.executeUpdate();
                    if(JdbcTemplate.this.logger.isDebugEnabled()) {
                        JdbcTemplate.this.logger.debug("SQL update affected " + rows + " rows");
                    }

                    var3 = Integer.valueOf(rows);
                } finally {
                    if(pss instanceof ParameterDisposer) {
                        ((ParameterDisposer)pss).cleanupParameters();
                    }

                }

                return var3;
            }
        })).intValue();
    }

    public int update(PreparedStatementCreator psc) throws DataAccessException {
        return this.update(psc, (PreparedStatementSetter)null);
    }

    public int update(PreparedStatementCreator psc, final KeyHolder generatedKeyHolder) throws DataAccessException {
        Assert.notNull(generatedKeyHolder, "KeyHolder must not be null");
        this.logger.debug("Executing SQL update and returning generated keys");
        return ((Integer)this.execute(psc, new PreparedStatementCallback<Integer>() {
            public Integer doInPreparedStatement(PreparedStatement ps) throws SQLException {
                int rows = ps.executeUpdate();
                List<Map<String, Object>> generatedKeys = generatedKeyHolder.getKeyList();
                generatedKeys.clear();
                ResultSet keys = ps.getGeneratedKeys();
                if(keys != null) {
                    try {
                        RowMapperResultSetExtractor<Map<String, Object>> rse = new RowMapperResultSetExtractor(JdbcTemplate.this.getColumnMapRowMapper(), 1);
                        generatedKeys.addAll(rse.extractData(keys));
                    } finally {
                        JdbcUtils.closeResultSet(keys);
                    }
                }

                if(JdbcTemplate.this.logger.isDebugEnabled()) {
                    JdbcTemplate.this.logger.debug("SQL update affected " + rows + " rows and returned " + generatedKeys.size() + " keys");
                }

                return Integer.valueOf(rows);
            }
        })).intValue();
    }

    public int update(String sql, PreparedStatementSetter pss) throws DataAccessException {
        return this.update((PreparedStatementCreator)(new JdbcTemplate.SimplePreparedStatementCreator(sql)), (PreparedStatementSetter)pss);
    }

    public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException {
        return this.update(sql, this.newArgTypePreparedStatementSetter(args, argTypes));
    }

    public int update(String sql, Object... args) throws DataAccessException {
        return this.update(sql, this.newArgPreparedStatementSetter(args));
    }

    public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss) throws DataAccessException {
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Executing SQL batch update [" + sql + "]");
        }

        return (int[])this.execute(sql, new PreparedStatementCallback<int[]>() {
            public int[] doInPreparedStatement(PreparedStatement ps) throws SQLException {
                try {
                    int batchSize = pss.getBatchSize();
                    InterruptibleBatchPreparedStatementSetter ipss = pss instanceof InterruptibleBatchPreparedStatementSetter?(InterruptibleBatchPreparedStatementSetter)pss:null;
                    if(JdbcUtils.supportsBatchUpdates(ps.getConnection())) {
                        int ixx = 0;

                        while(true) {
                            if(ixx < batchSize) {
                                pss.setValues(ps, ixx);
                                if(ipss == null || !ipss.isBatchExhausted(ixx)) {
                                    ps.addBatch();
                                    ++ixx;
                                    continue;
                                }
                            }

                            int[] var11 = ps.executeBatch();
                            return var11;
                        }
                    } else {
                        List<Integer> rowsAffected = new ArrayList();

                        for(int i = 0; i < batchSize; ++i) {
                            pss.setValues(ps, i);
                            if(ipss != null && ipss.isBatchExhausted(i)) {
                                break;
                            }

                            rowsAffected.add(Integer.valueOf(ps.executeUpdate()));
                        }

                        int[] rowsAffectedArray = new int[rowsAffected.size()];

                        for(int ix = 0; ix < rowsAffectedArray.length; ++ix) {
                            rowsAffectedArray[ix] = ((Integer)rowsAffected.get(ix)).intValue();
                        }

                        int[] var13 = rowsAffectedArray;
                        return var13;
                    }
                } finally {
                    if(pss instanceof ParameterDisposer) {
                        ((ParameterDisposer)pss).cleanupParameters();
                    }

                }
            }
        });
    }

    public int[] batchUpdate(String sql, List<Object[]> batchArgs) throws DataAccessException {
        return this.batchUpdate(sql, batchArgs, new int[0]);
    }

    public int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes) throws DataAccessException {
        return BatchUpdateUtils.executeBatchUpdate(sql, batchArgs, argTypes, this);
    }

    public <T> int[][] batchUpdate(String sql, final Collection<T> batchArgs, final int batchSize, final ParameterizedPreparedStatementSetter<T> pss) throws DataAccessException {
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Executing SQL batch update [" + sql + "] with a batch size of " + batchSize);
        }

        return (int[][])this.execute(sql, new PreparedStatementCallback<int[][]>() {
            public int[][] doInPreparedStatement(PreparedStatement ps) throws SQLException {
                ArrayList rowsAffected = new ArrayList();

                try {
                    boolean batchSupported = true;
                    if(!JdbcUtils.supportsBatchUpdates(ps.getConnection())) {
                        batchSupported = false;
                        JdbcTemplate.this.logger.warn("JDBC Driver does not support Batch updates; resorting to single statement execution");
                    }

                    int n = 0;
                    Iterator var5 = batchArgs.iterator();

                    while(var5.hasNext()) {
                        T obj = var5.next();
                        pss.setValues(ps, obj);
                        ++n;
                        int batchIdx;
                        if(batchSupported) {
                            ps.addBatch();
                            if(n % batchSize == 0 || n == batchArgs.size()) {
                                if(JdbcTemplate.this.logger.isDebugEnabled()) {
                                    batchIdx = n % batchSize == 0?n / batchSize:n / batchSize + 1;
                                    int items = n - (n % batchSize == 0?n / batchSize - 1:n / batchSize) * batchSize;
                                    JdbcTemplate.this.logger.debug("Sending SQL batch update #" + batchIdx + " with " + items + " items");
                                }

                                rowsAffected.add(ps.executeBatch());
                            }
                        } else {
                            batchIdx = ps.executeUpdate();
                            rowsAffected.add(new int[]{batchIdx});
                        }
                    }

                    int[][] result = new int[rowsAffected.size()][];

                    for(int i = 0; i < result.length; ++i) {
                        result[i] = (int[])rowsAffected.get(i);
                    }

                    int[][] var14 = result;
                    return var14;
                } finally {
                    if(pss instanceof ParameterDisposer) {
                        ((ParameterDisposer)pss).cleanupParameters();
                    }

                }
            }
        });
    }

    public <T> T execute(CallableStatementCreator csc, CallableStatementCallback<T> action) throws DataAccessException {
        Assert.notNull(csc, "CallableStatementCreator must not be null");
        Assert.notNull(action, "Callback object must not be null");
        if(this.logger.isDebugEnabled()) {
            String sql = getSql(csc);
            this.logger.debug("Calling stored procedure" + (sql != null?" [" + sql + "]":""));
        }

        Connection con = DataSourceUtils.getConnection(this.getDataSource());
        CallableStatement cs = null;

        Object var8;
        try {
            Connection conToUse = con;
            if(this.nativeJdbcExtractor != null) {
                conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
            }

            cs = csc.createCallableStatement(conToUse);
            this.applyStatementSettings(cs);
            CallableStatement csToUse = cs;
            if(this.nativeJdbcExtractor != null) {
                csToUse = this.nativeJdbcExtractor.getNativeCallableStatement(cs);
            }

            T result = action.doInCallableStatement(csToUse);
            this.handleWarnings((Statement)cs);
            var8 = result;
        } catch (SQLException var12) {
            if(csc instanceof ParameterDisposer) {
                ((ParameterDisposer)csc).cleanupParameters();
            }

            String sql = getSql(csc);
            csc = null;
            JdbcUtils.closeStatement(cs);
            cs = null;
            DataSourceUtils.releaseConnection(con, this.getDataSource());
            con = null;
            throw this.getExceptionTranslator().translate("CallableStatementCallback", sql, var12);
        } finally {
            if(csc instanceof ParameterDisposer) {
                ((ParameterDisposer)csc).cleanupParameters();
            }

            JdbcUtils.closeStatement(cs);
            DataSourceUtils.releaseConnection(con, this.getDataSource());
        }

        return var8;
    }

    public <T> T execute(String callString, CallableStatementCallback<T> action) throws DataAccessException {
        return this.execute((CallableStatementCreator)(new JdbcTemplate.SimpleCallableStatementCreator(callString)), (CallableStatementCallback)action);
    }

    public Map<String, Object> call(CallableStatementCreator csc, List<SqlParameter> declaredParameters) throws DataAccessException {
        final List<SqlParameter> updateCountParameters = new ArrayList();
        final List<SqlParameter> resultSetParameters = new ArrayList();
        final List<SqlParameter> callParameters = new ArrayList();
        Iterator var6 = declaredParameters.iterator();

        while(var6.hasNext()) {
            SqlParameter parameter = (SqlParameter)var6.next();
            if(parameter.isResultsParameter()) {
                if(parameter instanceof SqlReturnResultSet) {
                    resultSetParameters.add(parameter);
                } else {
                    updateCountParameters.add(parameter);
                }
            } else {
                callParameters.add(parameter);
            }
        }

        return (Map)this.execute(csc, new CallableStatementCallback<Map<String, Object>>() {
            public Map<String, Object> doInCallableStatement(CallableStatement cs) throws SQLException {
                boolean retVal = cs.execute();
                int updateCount = cs.getUpdateCount();
                if(JdbcTemplate.this.logger.isDebugEnabled()) {
                    JdbcTemplate.this.logger.debug("CallableStatement.execute() returned '" + retVal + "'");
                    JdbcTemplate.this.logger.debug("CallableStatement.getUpdateCount() returned " + updateCount);
                }

                Map<String, Object> returnedResults = JdbcTemplate.this.createResultsMap();
                if(retVal || updateCount != -1) {
                    returnedResults.putAll(JdbcTemplate.this.extractReturnedResults(cs, updateCountParameters, resultSetParameters, updateCount));
                }

                returnedResults.putAll(JdbcTemplate.this.extractOutputParameters(cs, callParameters));
                return returnedResults;
            }
        });
    }

    protected Map<String, Object> extractReturnedResults(CallableStatement cs, List<SqlParameter> updateCountParameters, List<SqlParameter> resultSetParameters, int updateCount) throws SQLException {
        Map<String, Object> returnedResults = new HashMap();
        int rsIndex = 0;
        int updateIndex = 0;
        boolean moreResults;
        if(!this.skipResultsProcessing) {
            do {
                String undeclaredName;
                if(updateCount == -1) {
                    if(resultSetParameters != null && resultSetParameters.size() > rsIndex) {
                        SqlReturnResultSet declaredRsParam = (SqlReturnResultSet)resultSetParameters.get(rsIndex);
                        returnedResults.putAll(this.processResultSet(cs.getResultSet(), declaredRsParam));
                        ++rsIndex;
                    } else if(!this.skipUndeclaredResults) {
                        undeclaredName = "#result-set-" + (rsIndex + 1);
                        SqlReturnResultSet undeclaredRsParam = new SqlReturnResultSet(undeclaredName, new ColumnMapRowMapper());
                        if(this.logger.isDebugEnabled()) {
                            this.logger.debug("Added default SqlReturnResultSet parameter named '" + undeclaredName + "'");
                        }

                        returnedResults.putAll(this.processResultSet(cs.getResultSet(), undeclaredRsParam));
                        ++rsIndex;
                    }
                } else if(updateCountParameters != null && updateCountParameters.size() > updateIndex) {
                    SqlReturnUpdateCount ucParam = (SqlReturnUpdateCount)updateCountParameters.get(updateIndex);
                    String declaredUcName = ucParam.getName();
                    returnedResults.put(declaredUcName, Integer.valueOf(updateCount));
                    ++updateIndex;
                } else if(!this.skipUndeclaredResults) {
                    undeclaredName = "#update-count-" + (updateIndex + 1);
                    if(this.logger.isDebugEnabled()) {
                        this.logger.debug("Added default SqlReturnUpdateCount parameter named '" + undeclaredName + "'");
                    }

                    returnedResults.put(undeclaredName, Integer.valueOf(updateCount));
                    ++updateIndex;
                }

                moreResults = cs.getMoreResults();
                updateCount = cs.getUpdateCount();
                if(this.logger.isDebugEnabled()) {
                    this.logger.debug("CallableStatement.getUpdateCount() returned " + updateCount);
                }
            } while(moreResults || updateCount != -1);
        }

        return returnedResults;
    }

    protected Map<String, Object> extractOutputParameters(CallableStatement cs, List<SqlParameter> parameters) throws SQLException {
        Map<String, Object> returnedResults = new HashMap();
        int sqlColIndex = 1;
        Iterator var5 = parameters.iterator();

        while(var5.hasNext()) {
            SqlParameter param = (SqlParameter)var5.next();
            if(param instanceof SqlOutParameter) {
                SqlOutParameter outParam = (SqlOutParameter)param;
                Object out;
                if(outParam.isReturnTypeSupported()) {
                    out = outParam.getSqlReturnType().getTypeValue(cs, sqlColIndex, outParam.getSqlType(), outParam.getTypeName());
                    returnedResults.put(outParam.getName(), out);
                } else {
                    out = cs.getObject(sqlColIndex);
                    if(out instanceof ResultSet) {
                        if(outParam.isResultSetSupported()) {
                            returnedResults.putAll(this.processResultSet((ResultSet)out, outParam));
                        } else {
                            String rsName = outParam.getName();
                            SqlReturnResultSet rsParam = new SqlReturnResultSet(rsName, new ColumnMapRowMapper());
                            returnedResults.putAll(this.processResultSet((ResultSet)out, rsParam));
                            if(this.logger.isDebugEnabled()) {
                                this.logger.debug("Added default SqlReturnResultSet parameter named '" + rsName + "'");
                            }
                        }
                    } else {
                        returnedResults.put(outParam.getName(), out);
                    }
                }
            }

            if(!param.isResultsParameter()) {
                ++sqlColIndex;
            }
        }

        return returnedResults;
    }

    protected Map<String, Object> processResultSet(ResultSet rs, ResultSetSupportingSqlParameter param) throws SQLException {
        if(rs == null) {
            return Collections.emptyMap();
        } else {
            HashMap returnedResults = new HashMap();

            try {
                ResultSet rsToUse = rs;
                if(this.nativeJdbcExtractor != null) {
                    rsToUse = this.nativeJdbcExtractor.getNativeResultSet(rs);
                }

                if(param.getRowMapper() != null) {
                    RowMapper rowMapper = param.getRowMapper();
                    Object result = (new RowMapperResultSetExtractor(rowMapper)).extractData(rsToUse);
                    returnedResults.put(param.getName(), result);
                } else if(param.getRowCallbackHandler() != null) {
                    RowCallbackHandler rch = param.getRowCallbackHandler();
                    (new JdbcTemplate.RowCallbackHandlerResultSetExtractor(rch)).extractData(rsToUse);
                    returnedResults.put(param.getName(), "ResultSet returned from stored procedure was processed");
                } else if(param.getResultSetExtractor() != null) {
                    Object result = param.getResultSetExtractor().extractData(rsToUse);
                    returnedResults.put(param.getName(), result);
                }
            } finally {
                JdbcUtils.closeResultSet(rs);
            }

            return returnedResults;
        }
    }

    protected RowMapper<Map<String, Object>> getColumnMapRowMapper() {
        return new ColumnMapRowMapper();
    }

    protected <T> RowMapper<T> getSingleColumnRowMapper(Class<T> requiredType) {
        return new SingleColumnRowMapper(requiredType);
    }

    protected Map<String, Object> createResultsMap() {
        return (Map)(this.isResultsMapCaseInsensitive()?new LinkedCaseInsensitiveMap():new LinkedHashMap());
    }

    protected void applyStatementSettings(Statement stmt) throws SQLException {
        int fetchSize = this.getFetchSize();
        if(fetchSize >= 0) {
            stmt.setFetchSize(fetchSize);
        }

        int maxRows = this.getMaxRows();
        if(maxRows >= 0) {
            stmt.setMaxRows(maxRows);
        }

        DataSourceUtils.applyTimeout(stmt, this.getDataSource(), this.getQueryTimeout());
    }

    protected PreparedStatementSetter newArgPreparedStatementSetter(Object[] args) {
        return new ArgumentPreparedStatementSetter(args);
    }

    protected PreparedStatementSetter newArgTypePreparedStatementSetter(Object[] args, int[] argTypes) {
        return new ArgumentTypePreparedStatementSetter(args, argTypes);
    }

    protected void handleWarnings(Statement stmt) throws SQLException {
        if(this.isIgnoreWarnings()) {
            if(this.logger.isDebugEnabled()) {
                for(SQLWarning warningToLog = stmt.getWarnings(); warningToLog != null; warningToLog = warningToLog.getNextWarning()) {
                    this.logger.debug("SQLWarning ignored: SQL state '" + warningToLog.getSQLState() + "', error code '" + warningToLog.getErrorCode() + "', message [" + warningToLog.getMessage() + "]");
                }
            }
        } else {
            this.handleWarnings(stmt.getWarnings());
        }

    }

    protected void handleWarnings(SQLWarning warning) throws SQLWarningException {
        if(warning != null) {
            throw new SQLWarningException("Warning not ignored", warning);
        }
    }

    private static String getSql(Object sqlProvider) {
        return sqlProvider instanceof SqlProvider?((SqlProvider)sqlProvider).getSql():null;
    }

    private static class RowCallbackHandlerResultSetExtractor implements ResultSetExtractor<Object> {
        private final RowCallbackHandler rch;

        public RowCallbackHandlerResultSetExtractor(RowCallbackHandler rch) {
            this.rch = rch;
        }

        public Object extractData(ResultSet rs) throws SQLException {
            while(rs.next()) {
                this.rch.processRow(rs);
            }

            return null;
        }
    }

    private static class SimpleCallableStatementCreator implements CallableStatementCreator, SqlProvider {
        private final String callString;

        public SimpleCallableStatementCreator(String callString) {
            Assert.notNull(callString, "Call string must not be null");
            this.callString = callString;
        }

        public CallableStatement createCallableStatement(Connection con) throws SQLException {
            return con.prepareCall(this.callString);
        }

        public String getSql() {
            return this.callString;
        }
    }

    private static class SimplePreparedStatementCreator implements PreparedStatementCreator, SqlProvider {
        private final String sql;

        public SimplePreparedStatementCreator(String sql) {
            Assert.notNull(sql, "SQL must not be null");
            this.sql = sql;
        }

        public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
            return con.prepareStatement(this.sql);
        }

        public String getSql() {
            return this.sql;
        }
    }

    private class CloseSuppressingInvocationHandler implements InvocationHandler {
        private final Connection target;

        public CloseSuppressingInvocationHandler(Connection target) {
            this.target = target;
        }

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if(method.getName().equals("equals")) {
                return Boolean.valueOf(proxy == args[0]);
            } else if(method.getName().equals("hashCode")) {
                return Integer.valueOf(System.identityHashCode(proxy));
            } else {
                if(method.getName().equals("unwrap")) {
                    if(((Class)args[0]).isInstance(proxy)) {
                        return proxy;
                    }
                } else if(method.getName().equals("isWrapperFor")) {
                    if(((Class)args[0]).isInstance(proxy)) {
                        return Boolean.valueOf(true);
                    }
                } else {
                    if(method.getName().equals("close")) {
                        return null;
                    }

                    if(method.getName().equals("isClosed")) {
                        return Boolean.valueOf(false);
                    }

                    if(method.getName().equals("getTargetConnection")) {
                        return this.target;
                    }
                }

                try {
                    Object retVal = method.invoke(this.target, args);
                    if(retVal instanceof Statement) {
                        JdbcTemplate.this.applyStatementSettings((Statement)retVal);
                    }

                    return retVal;
                } catch (InvocationTargetException var5) {
                    throw var5.getTargetException();
                }
            }
        }
    }
}

其中queryForObject方法有三個參數(shù):
a.String對象
包含了要從數(shù)據(jù)庫中查找數(shù)據(jù)的SQL
b.RowMapper對象
用來從ResultSet中提取數(shù)據(jù)并構(gòu)建對象
c.可變參數(shù)列表
列出要綁定到查詢上的索引值戳杀。
(3)DataSouce

package javax.sql;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Wrapper;


public interface DataSource  extends CommonDataSource,Wrapper {

  Connection getConnection() throws SQLException;
  /**
   *嘗試建立一個數(shù)據(jù)庫連接
   *username和Password都是數(shù)據(jù)庫的相關(guān)信息
   */
  Connection getConnection(String username, String password)
    throws SQLException;

}

(4)使用命名參數(shù)
命名參數(shù)可以賦予SQL中每個參數(shù)的一個明確的名字隔缀,在綁定值到查詢語句的時候通過該名字來引用參數(shù)猾瘸。
使用命名參數(shù)查詢淮悼,綁定值的順序不重要钉汗,可以按照名字來綁定值,如果查詢語句發(fā)生了變化導(dǎo)致參數(shù)順序與之前不一樣堰汉,我們不需要修改綁定的代碼远荠。
6.@Repository注解
該注解表明它將會在組件掃描的時候自動創(chuàng)建。它的構(gòu)造器上使用了@Inject注解守伸,因此創(chuàng)建的時候,會自動獲取一個JdbcOperations對象蠢涝。
7.JdbcOperations 接口
該接口的定義如下所示,它定義了JdbcTemplate所實現(xiàn)的操作惯吕。


package org.springframework.jdbc.core;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.rowset.SqlRowSet;

public interface JdbcOperations {
    <T> T execute(ConnectionCallback<T> var1) throws DataAccessException;

    <T> T execute(StatementCallback<T> var1) throws DataAccessException;

    void execute(String var1) throws DataAccessException;

    <T> T query(String var1, ResultSetExtractor<T> var2) throws DataAccessException;

    void query(String var1, RowCallbackHandler var2) throws DataAccessException;

    <T> List<T> query(String var1, RowMapper<T> var2) throws DataAccessException;

    <T> T queryForObject(String var1, RowMapper<T> var2) throws DataAccessException;

    <T> T queryForObject(String var1, Class<T> var2) throws DataAccessException;

    Map<String, Object> queryForMap(String var1) throws DataAccessException;

    <T> List<T> queryForList(String var1, Class<T> var2) throws DataAccessException;

    List<Map<String, Object>> queryForList(String var1) throws DataAccessException;

    SqlRowSet queryForRowSet(String var1) throws DataAccessException;

    int update(String var1) throws DataAccessException;

    int[] batchUpdate(String... var1) throws DataAccessException;

    <T> T execute(PreparedStatementCreator var1, PreparedStatementCallback<T> var2) throws DataAccessException;

    <T> T execute(String var1, PreparedStatementCallback<T> var2) throws DataAccessException;

    <T> T query(PreparedStatementCreator var1, ResultSetExtractor<T> var2) throws DataAccessException;

    <T> T query(String var1, PreparedStatementSetter var2, ResultSetExtractor<T> var3) throws DataAccessException;

    <T> T query(String var1, Object[] var2, int[] var3, ResultSetExtractor<T> var4) throws DataAccessException;

    <T> T query(String var1, Object[] var2, ResultSetExtractor<T> var3) throws DataAccessException;

    <T> T query(String var1, ResultSetExtractor<T> var2, Object... var3) throws DataAccessException;

    void query(PreparedStatementCreator var1, RowCallbackHandler var2) throws DataAccessException;

    void query(String var1, PreparedStatementSetter var2, RowCallbackHandler var3) throws DataAccessException;

    void query(String var1, Object[] var2, int[] var3, RowCallbackHandler var4) throws DataAccessException;

    void query(String var1, Object[] var2, RowCallbackHandler var3) throws DataAccessException;

    void query(String var1, RowCallbackHandler var2, Object... var3) throws DataAccessException;

    <T> List<T> query(PreparedStatementCreator var1, RowMapper<T> var2) throws DataAccessException;

    <T> List<T> query(String var1, PreparedStatementSetter var2, RowMapper<T> var3) throws DataAccessException;

    <T> List<T> query(String var1, Object[] var2, int[] var3, RowMapper<T> var4) throws DataAccessException;

    <T> List<T> query(String var1, Object[] var2, RowMapper<T> var3) throws DataAccessException;

    <T> List<T> query(String var1, RowMapper<T> var2, Object... var3) throws DataAccessException;

    <T> T queryForObject(String var1, Object[] var2, int[] var3, RowMapper<T> var4) throws DataAccessException;

    <T> T queryForObject(String var1, Object[] var2, RowMapper<T> var3) throws DataAccessException;

    <T> T queryForObject(String var1, RowMapper<T> var2, Object... var3) throws DataAccessException;

    <T> T queryForObject(String var1, Object[] var2, int[] var3, Class<T> var4) throws DataAccessException;

    <T> T queryForObject(String var1, Object[] var2, Class<T> var3) throws DataAccessException;

    <T> T queryForObject(String var1, Class<T> var2, Object... var3) throws DataAccessException;

    Map<String, Object> queryForMap(String var1, Object[] var2, int[] var3) throws DataAccessException;

    Map<String, Object> queryForMap(String var1, Object... var2) throws DataAccessException;

    <T> List<T> queryForList(String var1, Object[] var2, int[] var3, Class<T> var4) throws DataAccessException;

    <T> List<T> queryForList(String var1, Object[] var2, Class<T> var3) throws DataAccessException;

    <T> List<T> queryForList(String var1, Class<T> var2, Object... var3) throws DataAccessException;

    List<Map<String, Object>> queryForList(String var1, Object[] var2, int[] var3) throws DataAccessException;

    List<Map<String, Object>> queryForList(String var1, Object... var2) throws DataAccessException;

    SqlRowSet queryForRowSet(String var1, Object[] var2, int[] var3) throws DataAccessException;

    SqlRowSet queryForRowSet(String var1, Object... var2) throws DataAccessException;

    int update(PreparedStatementCreator var1) throws DataAccessException;

    int update(PreparedStatementCreator var1, KeyHolder var2) throws DataAccessException;

    int update(String var1, PreparedStatementSetter var2) throws DataAccessException;

    int update(String var1, Object[] var2, int[] var3) throws DataAccessException;

    int update(String var1, Object... var2) throws DataAccessException;

    int[] batchUpdate(String var1, BatchPreparedStatementSetter var2) throws DataAccessException;

    int[] batchUpdate(String var1, List<Object[]> var2) throws DataAccessException;

    int[] batchUpdate(String var1, List<Object[]> var2, int[] var3) throws DataAccessException;

    <T> int[][] batchUpdate(String var1, Collection<T> var2, int var3, ParameterizedPreparedStatementSetter<T> var4) throws DataAccessException;

    <T> T execute(CallableStatementCreator var1, CallableStatementCallback<T> var2) throws DataAccessException;

    <T> T execute(String var1, CallableStatementCallback<T> var2) throws DataAccessException;

    Map<String, Object> call(CallableStatementCreator var1, List<SqlParameter> var2) throws DataAccessException;
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吏颖,一起剝皮案震驚了整個濱河市半醉,隨后出現(xiàn)的幾起案子缩多,更是在濱河造成了極大的恐慌梁钾,老刑警劉巖姆泻,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異方咆,居然都是意外死亡,警方通過查閱死者的電腦和手機煌集,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門职恳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來色徘,“玉大人褂策,你說我怎么就攤上這事”楦悖” “怎么了溪猿?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵固该,是天一觀的道長剿骨。 經(jīng)常有香客問我,道長赏壹,這世上最難降的妖魔是什么衔沼? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任蝌借,我火速辦了婚禮,結(jié)果婚禮上指蚁,老公的妹妹穿的比我還像新娘菩佑。我一直安慰自己,他們只是感情好凝化,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著搓劫,像睡著了一般瞧哟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枪向,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天勤揩,我揣著相機與錄音,去河邊找鬼秘蛔。 笑死陨亡,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的深员。 我是一名探鬼主播负蠕,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼倦畅!你這毒婦竟也來了遮糖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤滔迈,失蹤者是張志新(化名)和其女友劉穎止吁,沒想到半個月后被辑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡敬惦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年盼理,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俄删。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡宏怔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出畴椰,到底是詐尸還是另有隱情臊诊,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布斜脂,位于F島的核電站抓艳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏帚戳。R本人自食惡果不足惜玷或,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望片任。 院中可真熱鬧偏友,春花似錦、人聲如沸对供。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽产场。三九已至鹅髓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間涝动,已是汗流浹背迈勋。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工炬灭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留醋粟,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓重归,卻偏偏與公主長得像米愿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鼻吮,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容