Mybatis+Springboot整體事務管理機制如下圖
由圖上可以清晰地看出來,Mybatis+Springboot的事務管理的核心類是SqlSessionFactoryBean,然後分爲兩大主線:Springboot事務管理一條主線,MyBatis自己管理事務一條主線;然後繼續,Mybatis自己管理事務也分兩條線:Jdbc管理事務一條線,Managed管理事務一條線。
- 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);
接着往下看
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的事務,實現了事務託管。
- Mybatis使用自己的事務管理
在這種情況下,Springboot未啓用事務管理,或者Mabatis配置了自己的事務管理,也就是this.transactionFactory不爲空,而此時我們只需要在配置文件中定義TransactionFactory爲JdbcTransactionFactory或者ManagedTransactionFactory,然後注入到SqlSessionFactoryBean中,即可實現Mybatis使用自己的事務管理機制。
--End--