Spring专题学习

18.Spring的数据访问

2018-09-18  本文已影响0人  Lee_java

1.数据访问对象DAO或者Repository组件
为了避免持久化的逻辑分散到应用中的各个组件中,最好是将数据访问的功能放到一个或者多个专注于此项任务的组件之中,这样的组件叫做数据访问对象或者Repository。
2.Spring的数据访问异常体系
(1)了解导致SQLException发生的异常
a.应用程序无法连接数据库
b.要执行的查询存在语法错误
c.查询中所使用的表或者列不存在
d.试图插入或者更新数据违反数据库约束的数据。
SQLException被当做处理数据访问所有问题的通用异常。对于所有的数据访问问题都会抛出SQLException异常,而不是对每种可能的问题都会有不同的异常类型。
(2)DataAccessException
Spring中的异常都是继承自DataAccessException,它是一个非检查型异常。


回想一下我们在用JDBC的时候,需要写好多重复的代码,比如创建连接,打开数据库连接,然后执行完SQL以后,还要捕获异常,关闭连接等,其中所不同的就是执行的SQL有所不同,其余的基本一样,此处我们可以使用设计模式中的模板方法,来将那些共通重复的代码进行抽取,建立一个模板,所改变的就是这个模板中的SQL。
模板方法就是将过程中与特定实现相关的部分委托给接口,而这个接口的不同实现定义了过程中的具体行为。
Spring将数据访问过程中固定的和可变的部分划分为两种:模板和回调。
(1)模板:管理过程中固定的部分。
(2)回调:处理自定义的数据访问代码。
Spring的模板类处理数据访问的固定部分(事务控制,管理资源以及处理异常);应用程序相关的数据访问(语句,绑定参数以及整理结果集在回调中实现处理)


Spring提供的数据访问模板.jpg

3.配置数据源
(1)Spring提供了上下文中配置数据源bean的多种方式:
a.通过JDBC驱动程序定义的数据源
b.通过JNDI查找的数据源
c.连接池的数据源
(2)JNDI数据源
a.优点
使用JNDI数据源,好处在于数据源完全可以在应用程序之外进行管理,这样应用程序只需要在访问数据库的时候查找数据源就可以。在应用服务器中管理的数据源通常以池的方式组织,从而具备良好的性能,并且还支持系统管理员对其进行切换。
b.在XML中配置
使用jee命名空间下的<jee:jndi-lookup>元素来检索JNDI中的任何对象并将其作为Spring的Bean。jndi-name属性就是制定JNDI资源的名称。resource-ref设置为true,这样给定的jndi-name将会自动添加java:comp/env的前缀。
c.使用Java进行配置Bean

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

(3)嵌入式的数据源
嵌入式数据库是应用的一部分,不是应用连接的独立数据库服务器。
a.在XML中配置数据源,可以使用jdbc命名空间。

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

(4)使用profile作为数据源
Spring提供了profile,需要做的就是将每个数据源配置在不同的profile中,通过使用profile功能,会在运行时选择数据源,这取决于哪一个profile处于激活状态。
a.Java配置

@Profile注解

b.XML配置

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

4.数据源连接池
在配置数据源的时候,我们也可以选择数据源连接池,有好多开源的,比如:
(1)Apache Commons DBCP
(2)C3P0
(3)BoneCP
这些连接池中的大多数能配置为Spring数据源,在一定程度上与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提供的连接并没有进行池化管理。
b.SimpleDriverDataSource与DriverManagerDataSource的工作方式类似,但是他直接使用JDBC的驱动,来解决在特定环境下的类加载问题,这样的环境包括OSGi容器。
c.SingleConnectionDataSouce在每个连接请求时都会返回同一个的连接。可以将其视为只有一个连接的池。
5.Spring中的JDBC模板
因为在JDBC中,我们会重复的写创建连接关闭资源等语句,Spring为我们提供了JDBC模板,它主要管理资源和异常处理,从而简化代码,让我们只需要编写从数据库读写数据的必须代码。
(1)Spring提供的JDBC模板:
a.JdbcTemplate
最基本的Spring JDBC模板,这个模板支持简单的JDBC数据库访问功能以及基于索引参数的查询。
b.NamedParameterJdbcTemplate
使用该模板类来执行查询时可以将值以命名参数的形式绑定到SQL中,不是使用简单的索引参数。
(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() {
    }
    /**
      *构造方法,注入一个DataSource作为参数
      */
    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方法有三个参数:
a.String对象
包含了要从数据库中查找数据的SQL
b.RowMapper对象
用来从ResultSet中提取数据并构建对象
c.可变参数列表
列出要绑定到查询上的索引值。
(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;
  /**
   *尝试建立一个数据库连接
   *username和Password都是数据库的相关信息
   */
  Connection getConnection(String username, String password)
    throws SQLException;

}

(4)使用命名参数
命名参数可以赋予SQL中每个参数的一个明确的名字,在绑定值到查询语句的时候通过该名字来引用参数。
使用命名参数查询,绑定值的顺序不重要,可以按照名字来绑定值,如果查询语句发生了变化导致参数顺序与之前不一样,我们不需要修改绑定的代码。
6.@Repository注解
该注解表明它将会在组件扫描的时候自动创建。它的构造器上使用了@Inject注解,因此创建的时候,会自动获取一个JdbcOperations对象。
7.JdbcOperations 接口
该接口的定义如下所示,它定义了JdbcTemplate所实现的操作。


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;
}

上一篇下一篇

猜你喜欢

热点阅读