JTA即Java-Transaction-API,JTA允許應用程式執行分散式交易處理,即兩個或多個在網路電腦資源上存取並且更新資料。 JDBC驅動程式對JTA的支援大大增強了資料存取能力。
XA協定是資料庫層面的一套分散式事務管理的規範,JTA是XA協定在Java中的實作,多個資料庫或是訊息廠商實作JTA介面,開發人員只需要呼叫SpringJTA介面即可實現JTA事務管理功能。
JTA事務比JDBC事務更強大。一個JTA事務可以有多個參與者,而一個JDBC事務則被限定在一個單一的資料庫連線。下列任一個Java平台的元件都可以參與一個JTA事務中
分散式事務(DistributedTransaction)包含事務管理器(TransactionManager)和一個或多個支援XA 協定的資源管理器( Resource Manager )。
資源管理器是任意類型的持久化資料儲存容器,例如在開發中常用的關聯式資料庫:MySQL,Oracle等,訊息中間件RocketMQ、RabbitMQ等。
事務管理器提供事務聲明,事務資源管理,同步,事務上下文傳播等功能,並且負責著所有事務參與單元者的相互通訊的責任。 JTA規範定義了事務管理器與其他事務參與者互動的接口,其他的事務參與者則與事務管理器互動。
專案整體結構圖
<!--SpringBoot核心依赖--> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <!--JTA组件核心依赖--> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-jta-atomikos</artifactid> </dependency>
這裡jtaManager的配置,在日誌輸出中非常關鍵。
spring: jta: transaction-manager-id: jtaManager # 数据源配置 datasource: type: com.alibaba.druid.pool.DruidDataSource data01: driverClassName: com.mysql.jdbc.Driver dbUrl: jdbc:mysql://localhost:3306/data-one username: root password: 000000 data02: driverClassName: com.mysql.jdbc.Driver dbUrl: jdbc:mysql://localhost:3306/data-two username: root password: 000000
這裡兩個資料庫連線的設定手法都是一樣的,可以在原始碼中自行下載閱讀。基本想法都是把資料來源交給JTA元件來統一管理,方便事務的通訊。
資料來源參數
@Component @ConfigurationProperties(prefix = "spring.datasource.data01") public class DruidOneParam { private String dbUrl; private String username; private String password; private String driverClassName; }
JTA元件配置
package com.jta.source.conifg; @Configuration @MapperScan(basePackages = {"com.jta.source.mapper.one"},sqlSessionTemplateRef = "data01SqlSessionTemplate") public class DruidOneConfig { private static final Logger LOGGER = LoggerFactory.getLogger(DruidOneConfig.class) ; @Resource private DruidOneParam druidOneParam ; @Primary @Bean("dataSourceOne") public DataSource dataSourceOne () { // 设置数据库连接 MysqlXADataSource mysqlXADataSource = new MysqlXADataSource(); mysqlXADataSource.setUrl(druidOneParam.getDbUrl()); mysqlXADataSource.setUser(druidOneParam.getUsername()); mysqlXADataSource.setPassword(druidOneParam.getPassword()); mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true); // 事务管理器 AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean(); atomikosDataSourceBean.setXaDataSource(mysqlXADataSource); atomikosDataSourceBean.setUniqueResourceName("dataSourceOne"); return atomikosDataSourceBean; } @Primary @Bean(name = "sqlSessionFactoryOne") public SqlSessionFactory sqlSessionFactoryOne( @Qualifier("dataSourceOne") DataSource dataSourceOne) throws Exception{ // 配置Session工厂 SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSourceOne); ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sessionFactory.setMapperLocations(resolver.getResources("classpath*:/dataOneMapper/*.xml")); return sessionFactory.getObject(); } @Primary @Bean(name = "data01SqlSessionTemplate") public SqlSessionTemplate sqlSessionTemplate( @Qualifier("sqlSessionFactoryOne") SqlSessionFactory sqlSessionFactory) { // 配置Session模板 return new SqlSessionTemplate(sqlSessionFactory); } }
這裡通過兩個方法測試結果做對比,在兩個資料來源之間進行資料操作時,只需要在介面方法加上@Transactional註解即可,這樣保證資料在兩個資料來源間也可以保證一致性。
@Service public class TransferServiceImpl implements TransferService { @Resource private UserAccount01Mapper userAccount01Mapper ; @Resource private UserAccount02Mapper userAccount02Mapper ; @Override public void transfer01() { userAccount01Mapper.transfer("jack",100); System.out.println("i="+1/0); userAccount02Mapper.transfer("tom",100); } @Transactional @Override public void transfer02() { userAccount01Mapper.transfer("jack",200); System.out.println("i="+1/0); userAccount02Mapper.transfer("tom",200); } }
以上是SpringBoot2中如何使用JTA元件實現多重資料來源事務管理的詳細內容。更多資訊請關注PHP中文網其他相關文章!