- JTA,即Java Transaction API,JTA允许应用程序执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据。JDBC驱动程序的JTA支持极大地增强了数据访问能力。
- JTA是基于XA标准制定的,采用两阶段提交的方式来管理分布式事务。即是一个事务管理器和多个资源管理器协作完成,第一阶段各个资源管理器提交,第二个阶段事务管理器需要查看资源管理器是否全部提交成功再提交。
- Java实现JTA强一致性的事务有很多种实现,笔者只是选择了atomikos的实现
SpringBoot整合
- 添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jta-atomikos</artifactId> </dependency>
- 准备两个数据源,笔者是和Mybatis整合的,因此需要将数据源和Mybatis单独绑定,如下:
/** * @Description 数据源的配置 * @Author CJB * @Date 2020/3/9 13:45 */ @Configuration public class DatasourceConfig{ /** * 第一个数据源的配置 */ @Configuration public static class DataSourceConfig1{ /** * 注入DruidXADataSource,Druid对JTA的支持,支持XA协议,采用两阶段事务的提交 * @return */ @ConfigurationProperties(prefix = "spring.datasource1") @Bean(value = "druidXADataSource1") public DruidXADataSource druidXADataSource1(){ return new DruidXADataSource(); } @Bean(name = "dataSource1") public DataSource dataSource1(@Qualifier("druidXADataSource1")DruidXADataSource dataSource){ AtomikosDataSourceBean xaDataSource=new AtomikosDataSourceBean(); xaDataSource.setXaDataSource(dataSource); xaDataSource.setUniqueResourceName("dataSource1"); return xaDataSource; } /** * Mybatis对多数据源的整合 * @param dataSource * @return * @throws Exception */ @Bean(name = "sqlSessionFactory1") public SqlSessionFactory sqlSessionFactory1(@Qualifier(value ="dataSource1")DataSource dataSource)throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.setMapUnderscoreToCamelCase(true); factory.setConfiguration(configuration); factory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper1/**/*.xml")); return factory.getObject(); } @Bean(name = "sqlSessionTemplate1") public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory1")SqlSessionFactory sqlSessionFactory){ return new SqlSessionTemplate(sqlSessionFactory); } /** * 配置mapper文件的扫描,注入mapper,也可以使用@MapperScan注解扫描,其中有一个属性指定sqlSessionFactory */ @Bean(value = "mapperScannerConfigurer1") public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); // 设置sqlSessionFactory名 mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory1"); // 设置接口映射器基础包名 mapperScannerConfigurer.setBasePackage("com.vivachek.service.dao"); return mapperScannerConfigurer; } } /** * 第二个数据源的配置 */ @Configuration public static class DataSourceConfig2{ @ConfigurationProperties(prefix = "spring.datasource2") @Bean(value = "druidXADataSource2") public DruidXADataSource druidXADataSource2(){ return new DruidXADataSource(); } @Bean(name = "dataSource2") public DataSource dataSource2(@Qualifier("druidXADataSource2")DruidXADataSource dataSource){ AtomikosDataSourceBean xaDataSource=new AtomikosDataSourceBean(); xaDataSource.setXaDataSource(dataSource); xaDataSource.setUniqueResourceName("dataSource2"); return xaDataSource; } //配置Mybatis @Bean(name = "sqlSessionFactory2") public SqlSessionFactory sqlSessionFactory1(@Qualifier(value ="dataSource2")DataSource dataSource)throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.setMapUnderscoreToCamelCase(true); factory.setConfiguration(configuration); factory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper2/**/*.xml")); return factory.getObject(); } @Bean(name = "sqlSessionTemplate2") public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory2")SqlSessionFactory sqlSessionFactory){ return new SqlSessionTemplate(sqlSessionFactory); } //配置Mapper扫描器,整合mybatis的时候多数据源必须配置 @Bean(value = "mapperScannerConfigurer2") public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); // 设置sqlSessionFactory名 mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory2"); // 设置接口映射器基础包名 mapperScannerConfigurer.setBasePackage("com.vivachek.service.dao2"); return mapperScannerConfigurer; } }
@Transactional
注意
-
使用
MapperScan
注解直接注入Mapper的时候需要使用sqlSessionFactoryRef
属性指定对应的SqlSessionFactory。当然笔者采用的配置的方式。 -
关于实现的原理这里不再细说了,读者自己读读源码就能很清楚的知晓了,SpringBoot源码万变不离自动配置类,设计到的配置类如下:
-
TransactionAutoConfiguration
:事务的自动配置类 -
DataSourceTransactionManagerAutoConfiguratio
:数据源事务管理器的自动配置类 -
AtomikosJtaConfiguratio
,JndiJtaConfiguration
:JTA事务的自动配置类
-
- 关于事务的执行原理可以看看笔者之前的文章,Spring事务源码解析
原文
https://chenjiabing666.github.io/2020/03/11/SpringBoot整合JTA/
本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » SpringBoot整合JTA