本文源码:GitHub·点这里 || GitEE·点这里java
JTA即Java-Transaction-API,JTA容许应用程序执行分布式事务处理,即在两个或多个网络计算机资源上访问而且更新数据。JDBC驱动程序对JTA的支持极大地加强了数据访问能力。mysql
XA协议是数据库层面的一套分布式事务管理的规范,JTA是XA协议在Java中的实现,多个数据库或是消息厂商实现JTA接口,开发人员只须要调用SpringJTA接口便可实现JTA事务管理功能。git
JTA事务比JDBC事务更强大。一个JTA事务能够有多个参与者,而一个JDBC事务则被限定在一个单一的数据库链接。下列任一个Java平台的组件均可以参与到一个JTA事务中github
分布式事务(DistributedTransaction)包括事务管理器(TransactionManager)和一个或多个支持 XA 协议的资源管理器 ( Resource Manager )。web
资源管理器是任意类型的持久化数据存储容器,例如在开发中经常使用的关系型数据库:MySQL,Oracle等,消息中间件RocketMQ、RabbitMQ等。spring
事务管理器提供事务声明,事务资源管理,同步,事务上下文传播等功能,而且负责着全部事务参与单元者的相互通信的责任。JTA规范定义了事务管理器与其余事务参与者交互的接口,其余的事务参与者与事务管理器进行交互。sql
项目总体结构图数据库
<!--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); } }
在上面JTA实现多数据源的事务管理,使用方式仍是相对简单,经过两阶段的提交,能够同时管理多个数据源的事务。可是暴露出的问题也很是明显,就是比较严重的性能问题,因为同时操做多个数据源,若是其中一个数据源获取数据的时间过长,会致使整个请求都很是的长,事务时间太长,锁数据的时间就会太长,天然就会致使低性能和低吞吐量。
所以在实际开发过程当中,对性能要求比较高的系统不多使用JTA组件作事务管理。做为一个轻量级的分布式事务解决方案,在小的系统中仍是值得推荐尝试的。
最后做为Java下的API,原理和用法仍是值得学习一下,开阔眼界和思路。
GitHub·地址 https://github.com/cicadasmile/middle-ware-parent GitEE·地址 https://gitee.com/cicadasmile/middle-ware-parent
推荐阅读:SpringBoot进阶系列