Mybatis+Springboot事务管理机制

Mybatis+Springboot整体事务管理机制如下图


Mybatis+Springboot整体事务管理机制

由图上可以清晰地看出来,Mybatis+Springboot的事务管理的核心类是SqlSessionFactoryBean,然后分为两大主线:Springboot事务管理一条主线,MyBatis自己管理事务一条主线;然后继续,Mybatis自己管理事务也分两条线:Jdbc管理事务一条线,Managed管理事务一条线。

  1. MyBatis使用Springboot的事务管理
    在Springboot初始化SqlSessionFactoryBean的类里,有段如下代码
targetConfiguration.setEnvironment(new Environment(this.environment,
    this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory,
        this.dataSource));

也就是说,如果Mybatis自己没有配置transactionFactory,那么就直接使用定义Springboot托管事务管理方案。所以,由此也可以得出一个结论,如果想使用Springboot托管Mybatis事务管理,就一定不能配置Mybatis自己的事务管理。
我们再来看SpringManagedTransactionFactory


SpringManagedTransactionFactory

它直接使用的是SpringManagedTransaction事务,其核心代码如下


SpringManagedTransaction

有此可见,其使用DataSourceUtils去获取Springboot的事务管理配置来管理Mybatis事务配置。
这就是Springboot托管Mybatis的事务的核心业务逻辑。
下面,我们来看看Springboot是如何把自己的事务管理传递给Mybatis的。

在我们使用的DataSourceTransactionManager中,有一段如下代码

    @Override
    protected Object doGetTransaction() {
        DataSourceTransactionObject txObject = new DataSourceTransactionObject();
        txObject.setSavepointAllowed(isNestedTransactionAllowed());
        ConnectionHolder conHolder =
                (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
        txObject.setConnectionHolder(conHolder, false);
        return txObject;
    }

其中,我们看到了

ConnectionHolder conHolder =
                (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());

这里大家可以看下TransactionSynchronizationManager的源代码,它借助ThreadLocal把事务定义存储到缓存中。
我们回头来看看Mybatis的Springboot事务管理类SpringManagedTransaction的openConnection()方法有下面代码

this.connection = DataSourceUtils.getConnection(this.dataSource);

接着往下看


DataSourceUtils.doGetConnection
    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;
    }

这里,如果能从TransactionSynchronizationManager缓存获取到connection那么就直接拿来用,如果获取不到就直接取数据库管理事务的链接。
而由前面的分析可知,在Springboot托管事务情况下,TransactionSynchronizationManager缓存中是有定义好事务管理信息的connection的,此时就是用Springboot的事务定义来管理Mybatis的事务,实现了事务托管。

  1. Mybatis使用自己的事务管理
    在这种情况下,Springboot未启用事务管理,或者Mabatis配置了自己的事务管理,也就是this.transactionFactory不为空,而此时我们只需要在配置文件中定义TransactionFactory为JdbcTransactionFactory或者ManagedTransactionFactory,然后注入到SqlSessionFactoryBean中,即可实现Mybatis使用自己的事务管理机制。
    --End--

你可能感兴趣的:(Mybatis+Springboot事务管理机制)