环境:idea+springboot2.x
场景:调用addUser方法执行对两个数据库的表操作,如果方法出现异常就回滚
user数据库中的users表
order数据库中的order_number表
将各自的事务管理器改为统一事务管理器即可
第一步pom文件配置jta atomikos 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
</dependencies>
第二步yml配置
spring:
datasource:
member:
url: jdbc:mysql://localhost:3306/user?useSSL=false
username: root
password: root
boorowConectionTimeout: 30
loginTimeout: 30
maintenanceInterval: 60
maxIdleTime: 60
maxLifetime: 20000
maxPoolSize: 25
minPoolSize: 3
uniqueResourceName: orderDatasource
order:
url: jdbc:mysql://localhost:3306/order?useSSL=false
username: root
password: root
borrowConnectionTimeout: 30
loginTimeout: 30
maintenanceInterval: 60
maxIdleTime: 60
maxLifetime: 20000
maxPoolSize: 25
minPoolSize: 3
uniqueResourceName: memberDatasource
第三步配置编写MemberConfig和OrdeerConfig配置类
@Data
@ConfigurationProperties(prefix = "spring.datasource.member")
public class MemberConfig {
private String url;
private String userName;
private String passWord;
private int minPoolSize;
private int maxPoolSize;
private int maxLifetime;
private int borrowConnectionTimeout;
private int loginTimeout;
private int maintenanceInterval;
private int maxIdleTime;
private String testQuery;
private String uniqueResourceName;
}
@Data
@ConfigurationProperties(prefix = "spring.datasource.order")
public class OrderConfig {
private String url;
private String userName;
private String passWord;
private int minPoolSize;
private int maxPoolSize;
private int maxLifetime;
private int borrowConnectionTimeout;
private int loginTimeout;
private int maintenanceInterval;
private int maxIdleTime;
private String testQuery;
private String uniqueResourceName;
}
第五步将DataSource改为xaDataSource
以MemberDataSourceConfig为例,OrderDataSourceConfig操作步骤相同
/**
* 创建DataSource 将我们的数据源统一交给我们的全局xa事务管理
* @return
*/
@Bean(name = "memberDataSource")
public DataSource memberDataSource(MemberConfig memberConfig) throws SQLException {
// 1.创建我们的xaDataSource
MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
mysqlXADataSource.setUrl(memberConfig.getUrl());
mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXADataSource.setPassword(memberConfig.getPassWord());
mysqlXADataSource.setUser(memberConfig.getUserName());
mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
// 2.注册到全局事务
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXADataSource);
xaDataSource.setUniqueResourceName(memberConfig.getUniqueResourceName());
xaDataSource.setMinPoolSize(memberConfig.getMinPoolSize());
xaDataSource.setMaxPoolSize(memberConfig.getMaxPoolSize());
xaDataSource.setMaxLifetime(memberConfig.getMaxLifetime());
xaDataSource.setBorrowConnectionTimeout(memberConfig.getBorrowConnectionTimeout());
xaDataSource.setLoginTimeout(memberConfig.getLoginTimeout());
xaDataSource.setMaintenanceInterval(memberConfig.getMaintenanceInterval());
xaDataSource.setMaxIdleTime(memberConfig.getMaxIdleTime());
xaDataSource.setTestQuery(memberConfig.getTestQuery());
// return DataSourceBuilder.create().build(); // 原始的DataSource
return xaDataSource; // 改为xaDataSource
}
第六步关闭事务管理器
以MemberDataSourceConfig为例,OrderDataSourceConfig操作步骤相同
执行代码
此时表中数据(已刷新)
放行
此时表中数据(已刷新)
事务回滚
输入合法数据进行测试
直接放行
数据已加入
页面信息