本章先以单个项目演示 跨库事务处理,在上一章(多数据源)的基础上来扩展。
1、新增 Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
<version>2.5.4</version>
</dependency>
2、新增 yml配置
spring:
jta:
log-dir: tx-logs
transaction-manager-id: txManager
atomikos:
properties:
log-base-dir: ./double-sql-log
3、修改 多数据源代码配置
修改 数据源1 里面的 orderLogDateSource
方法的配置
@ConfigurationProperties(prefix = "spring.datasource.order")
@Primary
public DataSource orderLogDateSource() throws SQLException {
// return DataSourceBuilder.create().build();//如果没有分布式事务,这个就可以了
// 有了分布式事务,用下面的这个,这几个get的参数,就不粘贴了,就是把yml的配置读取出来而已
MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
mysqlXADataSource.setUrl(dateSourceProperties.getOrder().getJdbcUrl());
mysqlXADataSource.setUser(dateSourceProperties.getOrder().getUsername());
mysqlXADataSource.setPassword(dateSourceProperties.getOrder().getPassword());
mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
// 将本地事务注册到创 Atomikos全局事务
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXADataSource);
xaDataSource.setUniqueResourceName("orderDataSource");
return xaDataSource;
}
再修改 数据源2 里面的 0
方法的配置
@Bean(name = "orderlogDataSource")
@ConfigurationProperties(prefix = "spring.datasource.orderlog")
public DataSource orderDataSource() throws SQLException {
// return DataSourceBuilder.create().build();//如果没有分布式事务,这个就可以了
MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
mysqlXADataSource.setUrl(dateSourceProperties.getOrderlog().getJdbcUrl());
mysqlXADataSource.setUser(dateSourceProperties.getOrderlog().getUsername());
mysqlXADataSource.setPassword(dateSourceProperties.getOrderlog().getPassword());
mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
// 将本地事务注册到创 Atomikos全局事务
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXADataSource);
xaDataSource.setUniqueResourceName("orderlogDataSource");
return xaDataSource;
}
4、用法
@Slf4j
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;// 数据源1
@Autowired
private OrderLogMapper orderLogMapper;// 数据源2
// 新增完配置之后,使用起来就跟使用普通的事务注解一样
@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
public void insert1() {
log.info("【OrderService.insert1】 开始执行");
String uuid = UUID.randomUUID().toString().replace("-", "").substring(10, 15);
OrderEntity orderEntity = new OrderEntity("order" + uuid, "订单信息插入成功");
orderMapper.insert1(orderEntity);
int i = 10/0;//这里模式报错,就可以看到两个数据库各自的表中都没有数据插入
System.out.println("**************************************************************");
OrderLogEntity logEntity = new OrderLogEntity("log" + uuid, "订单日志插入成功");
orderLogMapper.insert1(logEntity);
System.out.println("完毕!");
}
}