JdbcTemplate几种巧妙使用

前言:


        JDBC,已满足最基本的数据库操作需求;但是,在使用JDBC时,必须手动管理数据库资源,比如:获取PreparedStatement,设置SQL语句参数,关闭连接等步骤。

        JdbcTemplate,它SpringJDBC的封装,旨在使JDBC更加易于使用。并且JdbcTemplate处理了资源的建立和释放。

          ① 避免常见错误,比如忘了总要关闭连接。
          ② 它运行核心的JDBC工作流,如Statement的建立和执行,而我们只需要提供SQL语句和提取结果。

        方法:
       

 public JdbcTemplate(DataSource dataSource) 


         创建JdbcTemplate对象,方便执行SQL语句 
       

 public void execute(final String sql)

 
         execute可以执行所有SQL语句,因为没有返回值,一般用于执行DML语句。

         在JdbcTemplate中执行SQL语句的方法大致分为3类:

         1. void execute(String sql):

                  可以执行所有SQL语句,一般用于执行DDL(数据库定义语言)语句。

         2.int update(String sql, Object…args):

                  用于执行INSERT、UPDATE、DELETE等DML语句。 
                  sql:表示sql语句,允许有?占位符 
                  args:一个可变参数,表示用来替换问号占位符的实际参数

         3. queryXxx:用于DQL数据查询语句。                  

T queryForObject(String sql, Class requiredTyoe, Object…args) 
List query(String sql, RowMapper, Object…args)


1、简单的sql:删改查

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void deleteAllAndUpdateTaskAmount(TaskAmountModifyVO vo) {
        jdbcTemplate.update("delete from product_brokerage_rule where productId = ?", vo.getProductId());
    }

2、批量插入

private static final String UPDATE_TASK_AMOUNT_SQL = " insert into product_brokerage_rule(productId,relatedId,relatedName,relatedTypeCode,taskAmount) values (?,?,?,?,?) " +
            "ON DUPLICATE KEY UPDATE taskAmount = ?";

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void updateTaskAmount(TaskAmountModifyVO vo) {
        if (CollectionUtils.isEmpty(vo.getList())){
            return;
        }
        
        // 没找到的进行删除,已有的进行更新,新增的添加
        List<BrokerageRule> list = findByProductId(vo.getProductId());
        if (CollectionUtils.isNotEmpty(list)){
            Set<String> set = new HashSet<>();
            for (TaskAmountModifyListVO listVO : vo.getList()) {
                set.add(listVO.getRelatedTypeCode() + listVO.getRelatedId());
            }
            for (BrokerageRule rule : list) {
                if (!set.contains(rule.getRelatedTypeCode() + rule.getRelatedId())){
                    brokerageRuleDao.deleteById(rule.getId());
                }
            }
        }
        
        jdbcTemplate.batchUpdate(UPDATE_TASK_AMOUNT_SQL, vo.getList(), 20, new ParameterizedPreparedStatementSetter<TaskAmountModifyListVO>(){
            @Override
            public void setValues(PreparedStatement p, TaskAmountModifyListVO listVO) throws SQLException {
                p.setObject(1, vo.getProductId());
                p.setObject(2, listVO.getRelatedId());
                p.setObject(3, listVO.getRelatedName());
                p.setObject(4, listVO.getRelatedTypeCode());
                p.setObject(5, listVO.getTaskAmount());
                p.setObject(6, listVO.getTaskAmount());
            }
        });
    }

3、查询返回对应VO类的对象

    @Override
    public RuleStatisticalResultVO statisticalByProductIdAndSectionTypeCode(RuleStatisticalVO vo) {
        return jdbcTemplate.queryForObject("SELECT SUM(taskAmount) as totalTaskAmount,COUNT(1) as teamTotalNum, COUNT(IF(taskAmount>0,TRUE,NULL)) as  teamNum" +
                " FROM `product_brokerage_rule` WHERE productId=? AND relatedTypeCode=? ", new RowMapper<RuleStatisticalResultVO>() {
            @Override
            public RuleStatisticalResultVO mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new RuleStatisticalResultVO(rs.getLong(1), rs.getLong(2), rs.getLong(3));
            }
        }, vo.getProductId(), vo.getRelatedTypeCode());
    }

4、返回带泛型值

    @Override
    public List<SelectVO<String, Long>> applicationTypeBindInfo(IdVO vo) {
      return jdbcTemplate.query("select a.name, a.id from emp_application a,emp_application_type_application ta " +
              " where a.id  = ta.applicationId  and ta.applicationTypeId = ? order by ta.orderBy asc ", new RowMapper<SelectVO<String, Long>>() {
            @Override
            public SelectVO<String, Long> mapRow(ResultSet rs, int rowNum) throws SQLException {
                return SelectVO.newSelectVO(rs.getString(1), rs.getLong(2));
            }
        }, vo.getId());
    }

5、返回单个值

    @Override
    public Long countApplicationTypeById(Long id) {
        return jdbcTemplate.queryForObject("select count(1) from emp_application_type_application where applicationId = ?", Long.class, id);
    }

6、JpaConfig类,给出JdbcTemplate的实例

import com.myfutech.common.spring.jpa.base.impl.BaseJpaRepositoryImpl;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@ConditionalOnClass(HikariDataSource.class)
@EnableConfigurationProperties(ConnectionPoolProperties.class)
@EnableJpaRepositories(entityManagerFactoryRef = "userServiceEntityManagerFactory",
		transactionManagerRef = "userServiceTransactionManager", basePackages="com.myfutech.employee.service.provider.dao",
		repositoryBaseClass = BaseJpaRepositoryImpl.class)
public class JpaConfig {
	
	@Value("${userService.url}")
	private String url;
	@Value("${userService.username}")
	private String username;
	@Value("${userService.password}")
	private String password;
	
        @Autowired
        private ConnectionPoolProperties properties;
	

	@Bean("userServiceTransactionManager")
	PlatformTransactionManager userServiceTransactionManager() {
		return new JpaTransactionManager(userServiceEntityManagerFactory().getObject());
	}

	@Bean("userServiceEntityManagerFactory")
	LocalContainerEntityManagerFactoryBean userServiceEntityManagerFactory() {

		HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
		vendorAdapter.setGenerateDdl(true);

		LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
		Properties properties = new Properties();
		properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
		properties.setProperty("hibernate.jdbc.batch_size", "20");
		properties.setProperty("current_session_context_class", "jpa");
		properties.setProperty("hibernate.ejb.entitymanager_factory_name", "userServiceEntityManagerFactory");
		properties.setProperty("hibernate.hbm2ddl.auto", "none");
		
		factoryBean.setJpaProperties(properties);
		factoryBean.setDataSource(userServiceDataSource());
		factoryBean.setJpaVendorAdapter(vendorAdapter);
		factoryBean.setPackagesToScan("com.myfutech.employee.service.provider.model");
		return factoryBean;
	}

	@Bean
	JdbcTemplate initJdbcTemplate(){
		return new JdbcTemplate(userServiceDataSource());
	}

	@Bean("userServiceDataSource")
	DataSource userServiceDataSource() {
		HikariDataSource dataSource = new HikariDataSource();
		dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setJdbcUrl(url);
        dataSource.setDriverClassName(properties.getDriverClass());
	    dataSource.addDataSourceProperty("cachePrepStmts", properties.isCachePrepStmts());
        dataSource.addDataSourceProperty("prepStmtCacheSize", properties.getPrepStmtCacheSize());
        dataSource.addDataSourceProperty("prepStmtCacheSqlLimit", properties.getPrepStmtCacheSqlLimit());
        dataSource.addDataSourceProperty("useServerPrepStmts", properties.isUseServerPrepStmts());
        dataSource.addDataSourceProperty("useLocalSessionState", properties.isUseLocalSessionState());
        dataSource.addDataSourceProperty("rewriteBatchedStatements", properties.isRewriteBatchedStatements());
        dataSource.addDataSourceProperty("cacheResultSetMetadata", properties.isCacheResultSetMetadata());
        dataSource.addDataSourceProperty("cacheServerConfiguration", properties.isCacheServerConfiguration());
        dataSource.addDataSourceProperty("elideSetAutoCommits", properties.isElideSetAutoCommits());
        dataSource.addDataSourceProperty("maintainTimeStats", properties.isMaintainTimeStats());
        return dataSource;
	}
}

7、JdbcTemplate源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

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.UncategorizedSQLException;
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.rowset.SqlRowSet;
import org.springframework.lang.Nullable;
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 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() {
    }

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

    @Nullable
    public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");
        Connection con = DataSourceUtils.getConnection(this.obtainDataSource());

        Object var10;
        try {
            Connection conToUse = this.createConnectionProxy(con);
            var10 = action.doInConnection(conToUse);
        } catch (SQLException var8) {
            String sql = getSql(action);
            DataSourceUtils.releaseConnection(con, this.getDataSource());
            con = null;
            throw this.translateException("ConnectionCallback", sql, var8);
        } finally {
            DataSourceUtils.releaseConnection(con, this.getDataSource());
        }

        return var10;
    }

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

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

        Object var11;
        try {
            stmt = con.createStatement();
            this.applyStatementSettings(stmt);
            T result = action.doInStatement(stmt);
            this.handleWarnings(stmt);
            var11 = result;
        } catch (SQLException var9) {
            String sql = getSql(action);
            JdbcUtils.closeStatement(stmt);
            stmt = null;
            DataSourceUtils.releaseConnection(con, this.getDataSource());
            con = null;
            throw this.translateException("StatementCallback", sql, var9);
        } finally {
            JdbcUtils.closeStatement(stmt);
            DataSourceUtils.releaseConnection(con, this.getDataSource());
        }

        return var11;
    }

    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() {
            }

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

            public String getSql() {
                return sql;
            }
        }

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

    @Nullable
    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() {
            }

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

                Object var3;
                try {
                    rs = stmt.executeQuery(sql);
                    var3 = rse.extractData(rs);
                } finally {
                    JdbcUtils.closeResultSet(rs);
                }

                return var3;
            }

            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)result(this.query((String)sql, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper))));
    }

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

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

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

    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)result(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 rows;
            }

            public String getSql() {
                return sql;
            }
        }

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

    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 {
            @Nullable
            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(@Nullable String sqlx, String statement) {
                return StringUtils.isEmpty(sqlx) ? statement : sqlx + "; " + statement;
            }

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

        int[] result = (int[])this.execute((StatementCallback)(new BatchUpdateStatementCallback()));
        Assert.state(result != null, "No update counts");
        return result;
    }

    @Nullable
    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.obtainDataSource());
        PreparedStatement ps = null;

        Object var13;
        try {
            ps = psc.createPreparedStatement(con);
            this.applyStatementSettings(ps);
            T result = action.doInPreparedStatement(ps);
            this.handleWarnings((Statement)ps);
            var13 = result;
        } catch (SQLException var10) {
            if (psc instanceof ParameterDisposer) {
                ((ParameterDisposer)psc).cleanupParameters();
            }

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

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

        return var13;
    }

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

    @Nullable
    public <T> T query(PreparedStatementCreator psc, @Nullable 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>() {
            @Nullable
            public T doInPreparedStatement(PreparedStatement ps) throws SQLException {
                ResultSet rs = null;

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

                    rs = ps.executeQuery();
                    var3 = rse.extractData(rs);
                } finally {
                    JdbcUtils.closeResultSet(rs);
                    if (pss instanceof ParameterDisposer) {
                        ((ParameterDisposer)pss).cleanupParameters();
                    }

                }

                return var3;
            }
        });
    }

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

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

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

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

    @Nullable
    public <T> T query(String sql, ResultSetExtractor<T> rse, @Nullable 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, @Nullable 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, @Nullable 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)result(this.query((PreparedStatementCreator)psc, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper))));
    }

    public <T> List<T> query(String sql, @Nullable PreparedStatementSetter pss, RowMapper<T> rowMapper) throws DataAccessException {
        return (List)result(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)result(this.query(sql, args, argTypes, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper))));
    }

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

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

    @Nullable
    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.nullableSingleResult(results);
    }

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

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

    @Nullable
    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, @Nullable 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)result(this.queryForObject(sql, args, argTypes, this.getColumnMapRowMapper()));
    }

    public Map<String, Object> queryForMap(String sql, @Nullable Object... args) throws DataAccessException {
        return (Map)result(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, @Nullable 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, @Nullable Object... args) throws DataAccessException {
        return this.query(sql, args, this.getColumnMapRowMapper());
    }

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

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

    protected int update(PreparedStatementCreator psc, @Nullable PreparedStatementSetter pss) throws DataAccessException {
        this.logger.debug("Executing prepared SQL update");
        return updateCount((Integer)this.execute(psc, (ps) -> {
            Integer var4;
            try {
                if (pss != null) {
                    pss.setValues(ps);
                }

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

                var4 = rows;
            } finally {
                if (pss instanceof ParameterDisposer) {
                    ((ParameterDisposer)pss).cleanupParameters();
                }

            }

            return var4;
        }));
    }

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

    public int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder) throws DataAccessException {
        Assert.notNull(generatedKeyHolder, "KeyHolder must not be null");
        this.logger.debug("Executing SQL update and returning generated keys");
        return updateCount((Integer)this.execute(psc, (ps) -> {
            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(this.getColumnMapRowMapper(), 1);
                    generatedKeys.addAll((Collection)result(rse.extractData(keys)));
                } finally {
                    JdbcUtils.closeResultSet(keys);
                }
            }

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

            return rows;
        }));
    }

    public int update(String sql, @Nullable 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, @Nullable Object... args) throws DataAccessException {
        return this.update(sql, this.newArgPreparedStatementSetter(args));
    }

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

        int[] result = (int[])this.execute(sql, (ps) -> {
            try {
                int batchSize = pss.getBatchSize();
                InterruptibleBatchPreparedStatementSetter ipss = pss instanceof InterruptibleBatchPreparedStatementSetter ? (InterruptibleBatchPreparedStatementSetter)pss : null;
                if (!JdbcUtils.supportsBatchUpdates(ps.getConnection())) {
                    List<Integer> rowsAffected = new ArrayList();

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

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

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

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

                    int[] var13 = rowsAffectedArray;
                    return var13;
                } else {
                    int i = 0;

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

                        int[] var10 = ps.executeBatch();
                        return var10;
                    }
                }
            } finally {
                if (pss instanceof ParameterDisposer) {
                    ((ParameterDisposer)pss).cleanupParameters();
                }

            }
        });
        Assert.state(result != null, "No result array");
        return result;
    }

    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, Collection<T> batchArgs, int batchSize, ParameterizedPreparedStatementSetter<T> pss) throws DataAccessException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Executing SQL batch update [" + sql + "] with a batch size of " + batchSize);
        }

        int[][] result = (int[][])this.execute(sql, (ps) -> {
            ArrayList rowsAffected = new ArrayList();

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

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

                while(var8.hasNext()) {
                    T obj = var8.next();
                    pss.setValues(ps, obj);
                    ++n;
                    int batchIdx;
                    if (batchSupported) {
                        ps.addBatch();
                        if (n % batchSize == 0 || n == batchArgs.size()) {
                            if (this.logger.isDebugEnabled()) {
                                batchIdx = n % batchSize == 0 ? n / batchSize : n / batchSize + 1;
                                int items = n - (n % batchSize == 0 ? n / batchSize - 1 : n / batchSize) * batchSize;
                                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[][] result1 = new int[rowsAffected.size()][];

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

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

            }
        });
        Assert.state(result != null, "No result array");
        return result;
    }

    @Nullable
    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.obtainDataSource());
        CallableStatement cs = null;

        Object var13;
        try {
            cs = csc.createCallableStatement(con);
            this.applyStatementSettings(cs);
            T result = action.doInCallableStatement(cs);
            this.handleWarnings((Statement)cs);
            var13 = result;
        } catch (SQLException var10) {
            if (csc instanceof ParameterDisposer) {
                ((ParameterDisposer)csc).cleanupParameters();
            }

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

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

        return var13;
    }

    @Nullable
    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 {
        List<SqlParameter> updateCountParameters = new ArrayList();
        List<SqlParameter> resultSetParameters = new ArrayList();
        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);
            }
        }

        Map<String, Object> result = (Map)this.execute(csc, (cs) -> {
            boolean retVal = cs.execute();
            int updateCount = cs.getUpdateCount();
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("CallableStatement.execute() returned '" + retVal + "'");
                this.logger.debug("CallableStatement.getUpdateCount() returned " + updateCount);
            }

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

            returnedResults.putAll(this.extractOutputParameters(cs, callParameters));
            return returnedResults;
        });
        Assert.state(result != null, "No result map");
        return result;
    }

    protected Map<String, Object> extractReturnedResults(CallableStatement cs, @Nullable List<SqlParameter> updateCountParameters, @Nullable 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, this.getColumnMapRowMapper());
                        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, 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, 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;
                Assert.state(outParam.getName() != null, "Anonymous parameters not allowed");
                SqlReturnType returnType = outParam.getSqlReturnType();
                Object out;
                if (returnType != null) {
                    out = returnType.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, this.getColumnMapRowMapper());
                            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(@Nullable ResultSet rs, ResultSetSupportingSqlParameter param) throws SQLException {
        if (rs == null) {
            return Collections.emptyMap();
        } else {
            HashMap returnedResults = new HashMap();

            try {
                if (param.getRowMapper() != null) {
                    RowMapper<?> rowMapper = param.getRowMapper();
                    Object result = (new RowMapperResultSetExtractor(rowMapper)).extractData(rs);
                    returnedResults.put(param.getName(), result);
                } else if (param.getRowCallbackHandler() != null) {
                    RowCallbackHandler rch = param.getRowCallbackHandler();
                    (new JdbcTemplate.RowCallbackHandlerResultSetExtractor(rch)).extractData(rs);
                    returnedResults.put(param.getName(), "ResultSet returned from stored procedure was processed");
                } else if (param.getResultSetExtractor() != null) {
                    Object result = param.getResultSetExtractor().extractData(rs);
                    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 != -1) {
            stmt.setFetchSize(fetchSize);
        }

        int maxRows = this.getMaxRows();
        if (maxRows != -1) {
            stmt.setMaxRows(maxRows);
        }

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

    protected PreparedStatementSetter newArgPreparedStatementSetter(@Nullable 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(@Nullable SQLWarning warning) throws SQLWarningException {
        if (warning != null) {
            throw new SQLWarningException("Warning not ignored", warning);
        }
    }

    protected DataAccessException translateException(String task, @Nullable String sql, SQLException ex) {
        DataAccessException dae = this.getExceptionTranslator().translate(task, sql, ex);
        return (DataAccessException)(dae != null ? dae : new UncategorizedSQLException(task, sql, ex));
    }

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

    private static <T> T result(@Nullable T result) {
        Assert.state(result != null, "No result");
        return result;
    }

    private static int updateCount(@Nullable Integer result) {
        Assert.state(result != null, "No update count");
        return result;
    }

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

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

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

        @Nullable
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().equals("equals")) {
                return proxy == args[0];
            } else if (method.getName().equals("hashCode")) {
                return 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 true;
                    }
                } else {
                    if (method.getName().equals("close")) {
                        return null;
                    }

                    if (method.getName().equals("isClosed")) {
                        return 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();
                }
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/jiahao1186/article/details/91413037
今日推荐