前言:
JDBC,已满足最基本的数据库操作需求;但是,在使用JDBC时,必须手动管理数据库资源,比如:获取PreparedStatement,设置SQL语句参数,关闭连接等步骤。
JdbcTemplate ,它 是Spring 对JDBC 的封装,旨在使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 list = findByProductId(vo.getProductId());
if (CollectionUtils.isNotEmpty(list)){
Set 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(){
@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() {
@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> 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>() {
@Override
public SelectVO 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 execute(ConnectionCallback 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 execute(StatementCallback 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, 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 query(final String sql, final ResultSetExtractor 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, 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 List query(String sql, RowMapper rowMapper) throws DataAccessException {
return (List)result(this.query((String)sql, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper))));
}
public Map queryForMap(String sql) throws DataAccessException {
return (Map)result(this.queryForObject(sql, this.getColumnMapRowMapper()));
}
@Nullable
public T queryForObject(String sql, RowMapper rowMapper) throws DataAccessException {
List results = this.query(sql, rowMapper);
return DataAccessUtils.nullableSingleResult(results);
}
@Nullable
public T queryForObject(String sql, Class requiredType) throws DataAccessException {
return this.queryForObject(sql, this.getSingleColumnRowMapper(requiredType));
}
public List queryForList(String sql, Class elementType) throws DataAccessException {
return this.query(sql, this.getSingleColumnRowMapper(elementType));
}
public List> 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, 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, 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 execute(PreparedStatementCreator psc, PreparedStatementCallback 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 execute(String sql, PreparedStatementCallback action) throws DataAccessException {
return this.execute((PreparedStatementCreator)(new JdbcTemplate.SimplePreparedStatementCreator(sql)), (PreparedStatementCallback)action);
}
@Nullable
public T query(PreparedStatementCreator psc, @Nullable final PreparedStatementSetter pss, final ResultSetExtractor rse) throws DataAccessException {
Assert.notNull(rse, "ResultSetExtractor must not be null");
this.logger.debug("Executing prepared SQL query");
return this.execute(psc, new PreparedStatementCallback() {
@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 query(PreparedStatementCreator psc, ResultSetExtractor rse) throws DataAccessException {
return this.query((PreparedStatementCreator)psc, (PreparedStatementSetter)null, (ResultSetExtractor)rse);
}
@Nullable
public T query(String sql, @Nullable PreparedStatementSetter pss, ResultSetExtractor rse) throws DataAccessException {
return this.query((PreparedStatementCreator)(new JdbcTemplate.SimplePreparedStatementCreator(sql)), (PreparedStatementSetter)pss, (ResultSetExtractor)rse);
}
@Nullable
public T query(String sql, Object[] args, int[] argTypes, ResultSetExtractor rse) throws DataAccessException {
return this.query(sql, this.newArgTypePreparedStatementSetter(args, argTypes), rse);
}
@Nullable
public T query(String sql, @Nullable Object[] args, ResultSetExtractor rse) throws DataAccessException {
return this.query(sql, this.newArgPreparedStatementSetter(args), rse);
}
@Nullable
public T query(String sql, ResultSetExtractor 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 List query(PreparedStatementCreator psc, RowMapper rowMapper) throws DataAccessException {
return (List)result(this.query((PreparedStatementCreator)psc, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper))));
}
public List query(String sql, @Nullable PreparedStatementSetter pss, RowMapper rowMapper) throws DataAccessException {
return (List)result(this.query((String)sql, (PreparedStatementSetter)pss, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper))));
}
public List query(String sql, Object[] args, int[] argTypes, RowMapper rowMapper) throws DataAccessException {
return (List)result(this.query(sql, args, argTypes, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper))));
}
public List query(String sql, @Nullable Object[] args, RowMapper rowMapper) throws DataAccessException {
return (List)result(this.query((String)sql, (Object[])args, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper))));
}
public List query(String sql, RowMapper rowMapper, @Nullable Object... args) throws DataAccessException {
return (List)result(this.query((String)sql, (Object[])args, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper))));
}
@Nullable
public T queryForObject(String sql, Object[] args, int[] argTypes, RowMapper rowMapper) throws DataAccessException {
List results = (List)this.query(sql, args, argTypes, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper, 1)));
return DataAccessUtils.nullableSingleResult(results);
}
@Nullable
public T queryForObject(String sql, @Nullable Object[] args, RowMapper rowMapper) throws DataAccessException {
List results = (List)this.query((String)sql, (Object[])args, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper, 1)));
return DataAccessUtils.nullableSingleResult(results);
}
@Nullable
public T queryForObject(String sql, RowMapper rowMapper, @Nullable Object... args) throws DataAccessException {
List results = (List)this.query((String)sql, (Object[])args, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper, 1)));
return DataAccessUtils.nullableSingleResult(results);
}
@Nullable
public T queryForObject(String sql, Object[] args, int[] argTypes, Class requiredType) throws DataAccessException {
return this.queryForObject(sql, args, argTypes, this.getSingleColumnRowMapper(requiredType));
}
public T queryForObject(String sql, Object[] args, Class requiredType) throws DataAccessException {
return this.queryForObject(sql, args, this.getSingleColumnRowMapper(requiredType));
}
public T queryForObject(String sql, Class requiredType, @Nullable Object... args) throws DataAccessException {
return this.queryForObject(sql, args, this.getSingleColumnRowMapper(requiredType));
}
public Map queryForMap(String sql, Object[] args, int[] argTypes) throws DataAccessException {
return (Map)result(this.queryForObject(sql, args, argTypes, this.getColumnMapRowMapper()));
}
public Map queryForMap(String sql, @Nullable Object... args) throws DataAccessException {
return (Map)result(this.queryForObject(sql, args, this.getColumnMapRowMapper()));
}
public List queryForList(String sql, Object[] args, int[] argTypes, Class elementType) throws DataAccessException {
return this.query(sql, args, argTypes, this.getSingleColumnRowMapper(elementType));
}
public List queryForList(String sql, Object[] args, Class elementType) throws DataAccessException {
return this.query(sql, args, this.getSingleColumnRowMapper(elementType));
}
public List queryForList(String sql, Class elementType, @Nullable Object... args) throws DataAccessException {
return this.query(sql, args, this.getSingleColumnRowMapper(elementType));
}
public List> queryForList(String sql, Object[] args, int[] argTypes) throws DataAccessException {
return this.query(sql, args, argTypes, this.getColumnMapRowMapper());
}
public List> 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> generatedKeys = generatedKeyHolder.getKeyList();
generatedKeys.clear();
ResultSet keys = ps.getGeneratedKeys();
if (keys != null) {
try {
RowMapperResultSetExtractor> 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 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 batchArgs) throws DataAccessException {
return this.batchUpdate(sql, batchArgs, new int[0]);
}
public int[] batchUpdate(String sql, List batchArgs, int[] argTypes) throws DataAccessException {
return BatchUpdateUtils.executeBatchUpdate(sql, batchArgs, argTypes, this);
}
public int[][] batchUpdate(String sql, Collection batchArgs, int batchSize, ParameterizedPreparedStatementSetter 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 execute(CallableStatementCreator csc, CallableStatementCallback 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 execute(String callString, CallableStatementCallback action) throws DataAccessException {
return this.execute((CallableStatementCreator)(new JdbcTemplate.SimpleCallableStatementCreator(callString)), (CallableStatementCallback)action);
}
public Map call(CallableStatementCreator csc, List declaredParameters) throws DataAccessException {
List updateCountParameters = new ArrayList();
List resultSetParameters = new ArrayList();
List 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 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 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 extractReturnedResults(CallableStatement cs, @Nullable List updateCountParameters, @Nullable List resultSetParameters, int updateCount) throws SQLException {
Map 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 extractOutputParameters(CallableStatement cs, List parameters) throws SQLException {
Map 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 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> getColumnMapRowMapper() {
return new ColumnMapRowMapper();
}
protected RowMapper getSingleColumnRowMapper(Class requiredType) {
return new SingleColumnRowMapper(requiredType);
}
protected Map 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 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 {
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();
}
}
}
}
}