org.jfaster.mango.jdbc.JdbcTemplate Maven / Gradle / Ivy
/*
* Copyright 2014 mango.jfaster.org
*
* The Mango Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jfaster.mango.jdbc;
import org.jfaster.mango.binding.BoundSql;
import org.jfaster.mango.jdbc.exception.DataAccessException;
import org.jfaster.mango.jdbc.exception.DataRetrievalFailureException;
import org.jfaster.mango.mapper.RowMapper;
import org.jfaster.mango.transaction.DataSourceUtils;
import org.jfaster.mango.type.TypeHandler;
import org.jfaster.mango.util.local.CacheLoader;
import org.jfaster.mango.util.local.DoubleCheckCache;
import org.jfaster.mango.util.local.LoadingCache;
import org.jfaster.mango.util.logging.InternalLogger;
import org.jfaster.mango.util.logging.InternalLoggerFactory;
import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author ash
*/
public class JdbcTemplate implements JdbcOperations {
private final static InternalLogger logger = InternalLoggerFactory.getInstance(JdbcTemplate.class);
@Override
public T queryForObject(DataSource dataSource, BoundSql boundSql, RowMapper rowMapper)
throws DataAccessException {
return executeQuery(dataSource, boundSql, new ObjectResultSetExtractor(rowMapper));
}
@Override
public List queryForList(DataSource dataSource, BoundSql boundSql,
ListSupplier listSupplier, RowMapper rowMapper)
throws DataAccessException {
return executeQuery(dataSource, boundSql, new ListResultSetExtractor(listSupplier, rowMapper));
}
@Override
public Set queryForSet(DataSource dataSource, BoundSql boundSql,
SetSupplier setSupplier, RowMapper rowMapper)
throws DataAccessException {
return executeQuery(dataSource, boundSql, new SetResultSetExtractor(setSupplier, rowMapper));
}
@Override
public Object queryForArray(DataSource dataSource, BoundSql boundSql, RowMapper rowMapper)
throws DataAccessException {
return executeQuery(dataSource, boundSql, new ArrayResultSetExtractor(rowMapper));
}
@Override
public int update(DataSource dataSource, BoundSql boundSql)
throws DataAccessException {
return update(dataSource, boundSql, null);
}
@Override
public int update(DataSource dataSource, BoundSql boundSql, GeneratedKeyHolder holder)
throws DataAccessException {
Connection conn = DataSourceUtils.getConnection(dataSource);
PreparedStatement ps = null;
ResultSet rs = null;
String sql = boundSql.getSql();
try {
boolean needGenerateKey = holder != null;
ps = needGenerateKey ?
conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) : // 生成自增key
conn.prepareStatement(sql); // 不生成自增key
setValues(ps, boundSql);
if (logger.isDebugEnabled()) {
logger.debug("Executing \"{}\" {}", sql, boundSql.getArgs());
}
int r = ps.executeUpdate();
if (needGenerateKey) { // 生成自增key
rs = ps.getGeneratedKeys();
if (!rs.next()) {
throw new DataRetrievalFailureException("Unable to retrieve the generated key. " +
"Check that the table has an identity column enabled.");
}
Number key = holder.getTypeHandler().getResult(rs, 1);
holder.setKey(key);
}
return r;
} catch (SQLException e) {
closeResultSet(rs);
rs = null;
closeStatement(ps);
ps = null;
DataSourceUtils.releaseConnection(conn, dataSource);
conn = null;
throw getExceptionTranslator(dataSource).translate(sql, e);
} finally {
closeResultSet(rs);
closeStatement(ps);
DataSourceUtils.releaseConnection(conn, dataSource);
}
}
@Override
public int[] batchUpdate(DataSource dataSource, List boundSqls) throws DataAccessException {
return isUniqueSql(boundSqls) ?
batchUpdateForUniqueSql(dataSource, boundSqls) :
batchUpdateForDifferentSql(dataSource, boundSqls);
}
private T executeQuery(DataSource dataSource, BoundSql boundSql, ResultSetExtractor rse)
throws DataAccessException {
Connection conn = DataSourceUtils.getConnection(dataSource);
PreparedStatement ps = null;
ResultSet rs = null;
String sql = boundSql.getSql();
try {
ps = conn.prepareStatement(sql);
setValues(ps, boundSql);
if (logger.isDebugEnabled()) {
logger.debug("Executing \"{}\" {}", sql, boundSql.getArgs());
}
rs = ps.executeQuery();
return rse.extractData(rs);
} catch (SQLException e) {
closeResultSet(rs);
rs = null;
closeStatement(ps);
ps = null;
DataSourceUtils.releaseConnection(conn, dataSource);
conn = null;
throw getExceptionTranslator(dataSource).translate(sql, e);
} finally {
closeResultSet(rs);
closeStatement(ps);
DataSourceUtils.releaseConnection(conn, dataSource);
}
}
private int[] batchUpdateForUniqueSql(DataSource dataSource, List boundSqls)
throws DataAccessException {
Connection conn = DataSourceUtils.getConnection(dataSource);
PreparedStatement ps = null;
String sql = boundSqls.get(0).getSql();
try {
ps = conn.prepareStatement(sql);
setBatchValues(ps, boundSqls);
if (logger.isDebugEnabled()) {
List> debugBatchArgs = new ArrayList>(boundSqls.size());
for (BoundSql boundSql : boundSqls) {
debugBatchArgs.add(boundSql.getArgs());
}
logger.debug("Executing \"{}\" {}", sql, debugBatchArgs);
}
return ps.executeBatch();
} catch (SQLException e) {
closeStatement(ps);
ps = null;
DataSourceUtils.releaseConnection(conn, dataSource);
conn = null;
throw getExceptionTranslator(dataSource).translate(sql, e);
} finally {
closeStatement(ps);
DataSourceUtils.releaseConnection(conn, dataSource);
}
}
private int[] batchUpdateForDifferentSql(DataSource dataSource, List boundSqls)
throws DataAccessException {
int size = boundSqls.size();
int[] r = new int[size];
Connection conn = DataSourceUtils.getConnection(dataSource);
try {
for (int i = 0; i < size; i++) {
BoundSql boundSql = boundSqls.get(i);
String sql = boundSql.getSql();
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
setValues(ps, boundSql);
if (logger.isDebugEnabled()) {
logger.debug("Executing \"{}\" {}", sql, boundSql.getArgs());
}
r[i] = ps.executeUpdate();
} catch (SQLException e) {
closeStatement(ps);
ps = null;
DataSourceUtils.releaseConnection(conn, dataSource);
conn = null;
throw getExceptionTranslator(dataSource).translate(sql, e);
} finally {
closeStatement(ps);
}
}
} finally {
DataSourceUtils.releaseConnection(conn, dataSource);
}
return r;
}
@SuppressWarnings("unchecked")
private void setValues(PreparedStatement ps, BoundSql boundSql) throws SQLException {
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy