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面试题的资料