spring4.3.6源代码 - tx - 如何支持@Transactional注解下的数据库操作使用同一个连接

37 篇文章 0 订阅

 

1、居于 TransactionSynchronizationManager.getResource(this.dataSource)  从线程上下文resources获取ConnectionHolder对象

 

spring-tx(@Transactional)


// org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
    // new 创建 DataSourceTransactionObject 对象,并依赖从本地线程上下文resources中获取的ConnectionHolder对象,可能为null
    Object transaction = doGetTransaction(); // !!! 数据源为key,从线程上线文中获取 

    // Cache debug flag to avoid repeated checks.
    boolean debugEnabled = logger.isDebugEnabled();

    if (definition == null) {
        // Use defaults if no transaction definition given.
        definition = new DefaultTransactionDefinition();
    }

    if (isExistingTransaction(transaction)) { // ConnectionHolder不为null,且事务处于活跃
        // Existing transaction found -> check propagation behavior to find out how to behave.
        return handleExistingTransaction(definition, transaction, debugEnabled);
    }

    // Check definition settings for new transaction.
    if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
        throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
    }

    // No existing transaction found -> check propagation behavior to find out how to proceed.
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
        throw new IllegalTransactionStateException(
                "No existing transaction found for transaction marked with propagation 'mandatory'");
    }
    else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
            definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
            definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {

        SuspendedResourcesHolder suspendedResources = suspend(null);  // 获取线程上下文的synchronizations列表
        if (debugEnabled) {
            logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
        }
        try {
            boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
            DefaultTransactionStatus status = newTransactionStatus(
                    definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); // 创建事务状态器

            /*
                1、从数据源获取connection,设置隔离级别、自动提交、超时信息
                2、创建ConnectionHolder对象,依赖connection
                3、!!! 把ConnectionHolder放入线程上下文的resources对象
             */
            doBegin(transaction, definition); // 开启事务,把连接放入线程上下文

            /*
                如果是新事务,那么更新配置到线程上下文 actualTransactionActive、currentTransactionIsolationLevel、currentTransactionReadOnly、currentTransactionName
             */
            prepareSynchronization(status, definition); //
            return status;
        }
        catch (RuntimeException ex) {
            resume(null, suspendedResources);
            throw ex;
        }
        catch (Error err) {
            resume(null, suspendedResources);
            throw err;
        }
    }
    else {
        // Create "empty" transaction: no actual transaction, but potentially synchronization.
        if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
            logger.warn("Custom isolation level specified but no actual transaction initiated; " +
                    "isolation level will effectively be ignored: " + definition);
        }
        boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
        return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
    }
}

 

spring-jdbc 获取连接

居于 org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection

// org.springframework.jdbc.core.JdbcTemplate#execute(org.springframework.jdbc.core.PreparedStatementCreator, org.springframework.jdbc.core.PreparedStatementCallback<T>)

@Override
public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
    Assert.notNull(action, "Callback object must not be null");

    Connection con = DataSourceUtils.getConnection(getDataSource()); // !!! 获取数据库连接
    try {
        Connection conToUse = con;
        if (this.nativeJdbcExtractor != null) {
            // Extract native JDBC Connection, castable to OracleConnection or the like.
            conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
        }
        else {
            // Create close-suppressing Connection proxy, also preparing returned Statements.
            conToUse = createConnectionProxy(con);
        }
        return action.doInConnection(conToUse);
    }
    catch (SQLException ex) {
        // Release Connection early, to avoid potential connection pool deadlock
        // in the case when the exception translator hasn't been initialized yet.
        DataSourceUtils.releaseConnection(con, getDataSource());
        con = null;
        throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
    }
    finally {
        DataSourceUtils.releaseConnection(con, getDataSource()); // 释放
    }
}
// org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
public static Connection doGetConnection(DataSource dataSource) throws SQLException {
    Assert.notNull(dataSource, "No DataSource specified");

    // 数据源为key,从线程上线文resources中获取
    // tx 对象 org.springframework.transaction.support.TransactionSynchronizationManager
    ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
    if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
        conHolder.requested();
        if (!conHolder.hasConnection()) {
            logger.debug("Fetching resumed JDBC Connection from DataSource");
            conHolder.setConnection(dataSource.getConnection());
        }
        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 = dataSource.getConnection();

    if (TransactionSynchronizationManager.isSynchronizationActive()) {
        logger.debug("Registering transaction synchronization for JDBC Connection");
        // Use same Connection for further JDBC actions within the transaction.
        // Thread-bound object will get removed by synchronization at transaction completion.
        ConnectionHolder holderToUse = conHolder;
        if (holderToUse == null) {
            holderToUse = new ConnectionHolder(con);
        }
        else {
            holderToUse.setConnection(con);
        }
        holderToUse.requested();

        // 事务添加到 synchronizations
        TransactionSynchronizationManager.registerSynchronization(
                new ConnectionSynchronization(holderToUse, dataSource));
        holderToUse.setSynchronizedWithTransaction(true);
        if (holderToUse != conHolder) {
            // 数据源为key,连接设置线程上下文resources中
            TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
        }
    }

    return con;
}

mybatis-spring 获取连接

居于 org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection

// org.mybatis.spring.transaction.SpringManagedTransaction#getConnection


public Connection getConnection() throws SQLException {
    if (this.connection == null) {
      openConnection();
    }
    return this.connection;
}

private void openConnection() throws SQLException {
    // 使用spring-jdbc的类
    // org.springframework.jdbc.datasource.DataSourceUtils#getConnection
    this.connection = DataSourceUtils.getConnection(this.dataSource); // !!! 获取连接
    this.autoCommit = this.connection.getAutoCommit();
    this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);

    LOGGER.debug(() ->
        "JDBC Connection ["
            + this.connection
            + "] will"
            + (this.isConnectionTransactional ? " " : " not ")
            + "be managed by Spring");
}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值