基于Spring 5.2.6.RELEASE
1、执行ddl
//org.springframework.jdbc.core.JdbcTemplate#execute
public void execute(final String sql) throws DataAccessException {
if (logger.isDebugEnabled()) {
logger.debug("Executing SQL statement [" + sql + "]");
}
/**
* Callback to execute the statement.
*/
class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
@Override
@Nullable
public Object doInStatement(Statement stmt) throws SQLException {
//调用statement执行sql
stmt.execute(sql);
return null;
}
@Override
public String getSql() {
return sql;
}
}
execute(new ExecuteStatementCallback());
}
//org.springframework.jdbc.core.JdbcTemplate#execute(org.springframework.jdbc.core.StatementCallback<T>)
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
//获取连接
Connection con = DataSourceUtils.getConnection(obtainDataSource());
Statement stmt = null;
try {
//获取statement
stmt = con.createStatement();
//设置statement属性
applyStatementSettings(stmt);
//statement执行sql
T result = action.doInStatement(stmt);
//处理警告
handleWarnings(stmt);
return result;
}
catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
String sql = getSql(action);
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw translateException("StatementCallback", sql, ex);
}
finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
1.1、获取连接
1.1.1、获取数据源
JdbcTemplate继承了JdbcAccessor,直接调用父类的方法
//org.springframework.jdbc.support.JdbcAccessor#obtainDataSource
protected DataSource obtainDataSource() {
DataSource dataSource = getDataSource();
Assert.state(dataSource != null, "No DataSource set");
return dataSource;
}
private DataSource dataSource;
//org.springframework.jdbc.support.JdbcAccessor#getDataSource
public DataSource getDataSource() {
return this.dataSource;
}
数据源是在注册JdbcTemplate的时候设置的,JdbcAccessor 还实现了 InitializingBean,用来检查数据源。
1.1.2、获取连接
//org.springframework.jdbc.datasource.DataSourceUtils#getConnection
public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
try {
return doGetConnection(dataSource);
}
catch (SQLException ex) {
throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex);
}
catch (IllegalStateException ex) {
throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection: " + ex.getMessage());
}
}
//org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
public static Connection doGetConnection(DataSource dataSource) throws SQLException {
Assert.notNull(dataSource, "No DataSource specified");
//从事务管理器获取ConnectionHolder
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
//增加计数,大于0表示连接打开了
conHolder.requested();
//没有连接
if (!conHolder.hasConnection()) {
logger.debug("Fetching resumed JDBC Connection from DataSource");
//获取连接并设置到ConnectionHolder
conHolder.setConnection(fetchConnection(dataSource));
}
//返回
return conHolder.getConnection();
}
// Else we either got no holder or an empty thread-bound holder here.
logger.debug("Fetching JDBC Connection from DataSource");
//没有连接,则获取连接
Connection con = fetchConnection(dataSource);
//事务管理
if (TransactionSynchronizationManager.isSynchronizationActive()) {
try {
// Use same Connection for further JDBC actions within the transaction.
// Thread-bound object will get removed by synchronization at transaction completion.
//将连接设置到ConnectionHolder
ConnectionHolder holderToUse = conHolder;
if (holderToUse == null) {
holderToUse = new ConnectionHolder(con);
}
else {
holderToUse.setConnection(con);
}
holderToUse.requested();
//向事务管理器注册连接
TransactionSynchronizationManager.registerSynchronization(
new ConnectionSynchronization(holderToUse, dataSource));
holderToUse.setSynchronizedWithTransaction(true);
//新创建的ConnectionHolder
if (holderToUse != conHolder) {
//绑定数据源
TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
}
}
catch (RuntimeException ex) {
// Unexpected exception from external delegation call -> close Connection and rethrow.
releaseConnection(con, dataSource);
throw ex;
}
}
return con;
}
1.1.2.1、从事务管理器获取链接
//org.springframework.transaction.support.TransactionSynchronizationManager#getResource
public static Object getResource(Object key) {
//获取连接的key,这里传入的是DataSource
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
//获取ConnectionHolder
Object value = doGetResource(actualKey);
if (value != null && logger.isTraceEnabled()) {
logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +
Thread.currentThread().getName() + "]");
}
return value;
}
1.1.2.1.1、获取真正的数据源
private static final boolean aopAvailable = ClassUtils.isPresent(
"org.springframework.aop.scope.ScopedObject", TransactionSynchronizationUtils.class.getClassLoader());
//org.springframework.transaction.support.TransactionSynchronizationUtils#unwrapResourceIfNecessary
static Object unwrapResourceIfNecessary(Object resource) {
Assert.notNull(resource, "Resource must not be null");
Object resourceRef = resource;
// unwrap infrastructure proxy
if (resourceRef instanceof InfrastructureProxy) {
resourceRef = ((InfrastructureProxy) resourceRef).getWrappedObject();
}
//aop
if (aopAvailable) {
// now unwrap scoped proxy
resourceRef = ScopedProxyUnwrapper.unwrapIfNecessary(resourceRef);
}
return resourceRef;
}
1.1.2.1.2、获取连接
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
//org.springframework.transaction.support.TransactionSynchronizationManager#doGetResource
private static Object doGetResource(Object actualKey) {
//获取线程变量
Map<Object, Object> map = resources.get();
if (map == null) {
return null;
}
//获取连接
Object value = map.get(actualKey);
// Transparently remove ResourceHolder that was marked as void...
if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
map.remove(actualKey);
// Remove entire ThreadLocal if empty...
if (map.isEmpty()) {
resources.remove();
}
value = null;
}
return value;
}
1.1.2.2、获取连接
//org.springframework.jdbc.datasource.DataSourceUtils#fetchConnection
private static Connection fetchConnection(DataSource dataSource) throws SQLException {
//获取连接,各种数据源产品有不同的实现
Connection con = dataSource.getConnection();
if (con == null) {
throw new IllegalStateException("DataSource returned null from getConnection(): " + dataSource);
}
return con;
}
1.1.2.3、判断当前线程事务是否激活
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<>("Transaction synchronizations");
//org.springframework.transaction.support.TransactionSynchronizationManager#isSynchronizationActive
public static boolean isSynchronizationActive() {
return (synchronizations.get() != null);
}
1.1.2.4、注册当前线程事务
//org.springframework.transaction.support.TransactionSynchronizationManager#registerSynchronization
public static void registerSynchronization(TransactionSynchronization synchronization) throws IllegalStateException {
Assert.notNull(synchronization, "TransactionSynchronization must not be null");
Set<TransactionSynchronization> synchs = synchronizations.get();
if (synchs == null) {
throw new IllegalStateException("Transaction synchronization is not active");
}
synchs.add(synchronization);
}
1.1.2.5、绑定数据源和连接
//org.springframework.transaction.support.TransactionSynchronizationManager#bindResource
public static void bindResource(Object key, Object value) throws IllegalStateException {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Assert.notNull(value, "Value must not be null");
Map<Object, Object> map = resources.get();
// set ThreadLocal Map if none found
if (map == null) {
map = new HashMap<>();
resources.set(map);
}
Object oldValue = map.put(actualKey, value);
// Transparently suppress a ResourceHolder that was marked as void...
if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) {
oldValue = null;
}
if (oldValue != null) {
throw new IllegalStateException("Already value [" + oldValue + "] for key [" +
actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
}
if (logger.isTraceEnabled()) {
logger.trace("Bound value [" + value + "] for key [" + actualKey + "] to thread [" +
Thread.currentThread().getName() + "]");
}
}
1.2、设置Statement属性
//org.springframework.jdbc.core.JdbcTemplate#applyStatementSettings
protected void applyStatementSettings(Statement stmt) throws SQLException {
//设置条数
int fetchSize = getFetchSize();
if (fetchSize != -1) {
stmt.setFetchSize(fetchSize);
}
//设置最大行数
int maxRows = getMaxRows();
if (maxRows != -1) {
stmt.setMaxRows(maxRows);
}
//设置超时时间
DataSourceUtils.applyTimeout(stmt, getDataSource(), getQueryTimeout());
}
1.3、释放连接
//org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
public static void releaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) {
try {
doReleaseConnection(con, dataSource);
}
catch (SQLException ex) {
logger.debug("Could not close JDBC Connection", ex);
}
catch (Throwable ex) {
logger.debug("Unexpected exception on closing JDBC Connection", ex);
}
}
//org.springframework.jdbc.datasource.DataSourceUtils#doReleaseConnection
public static void doReleaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) throws SQLException {
if (con == null) {
return;
}
//数据源不为空
if (dataSource != null) {
//获取 ConnectionHolder
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
if (conHolder != null && connectionEquals(conHolder, con)) {
// It's the transactional Connection: Don't close it.
//释放
conHolder.released();
return;
}
}
//关闭连接
doCloseConnection(con, dataSource);
}
1.3.1、释放连接
//org.springframework.jdbc.datasource.ConnectionHolder#released
public void released() {
//计数器减一
super.released();
//计数器不大于0,说明连接没有使用了
if (!isOpen() && this.currentConnection != null) {
if (this.connectionHandle != null) {
//释放连接,空方法
this.connectionHandle.releaseConnection(this.currentConnection);
}
this.currentConnection = null;
}
}
1.3.2、关闭连接
//org.springframework.jdbc.datasource.DataSourceUtils#doCloseConnection
public static void doCloseConnection(Connection con, @Nullable DataSource dataSource) throws SQLException {
if (!(dataSource instanceof SmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {
//调用 connection 的 close方法
con.close();
}
}
版权声明:本文为xuwenjingrenca原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。