Spring JdbcTemplate1-ddl

基于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版权协议,转载请附上原文出处链接和本声明。