Mybatis+Springboot事务管理机制详解

2,075 阅读2分钟

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

它直接使用的是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的事务,实现了事务托管。

2、Mybatis使用自己的事务管理

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

个人简介:荡不羁,一生所爱。Java耕耘者(微信公众号ID:Java耕耘者),欢迎关注。可获得详细的2020面试题的资料