JTA
JTA,即Java Transaction API,JTA允许应用程序执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据。
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
YML配置
spring:
jta:
atomikos:
datasource:
primary:
xa-properties:
url: jdbc:mysql://host:3306/test-source?useUnicode=true&characterEncoding=utf-8
user: ENC(leNmW2mZWHadQdE9aq5iIw==)
password: ENC(k5SFNga7adQ/xFsxzbe3Rbe3pZEow0KdSj0pWlDjDJA=)
xa-data-source-class-name: com.mysql.cj.jdbc.MysqlXADataSource
unique-resource-name: coolSource
max-pool-size: 25
min-pool-size: 3
max-lifetime: 20000
borrow-connection-timeout: 10000
secondary:
xa-properties:
url: jdbc:mysql://host:3306/test-user?useUnicode=true&characterEncoding=utf-8
user: ENC(leNmW2mZWHadQdE9aq5iIw==)
password: ENC(k5SFNga7adQ/xFsxzbe3Rbe3pZEow0KdSj0pWlDjDJA=)
xa-data-source-class-name: com.mysql.cj.jdbc.MysqlXADataSource
unique-resource-name: coolUser
max-pool-size: 25
min-pool-size: 3
max-lifetime: 20000
borrow-connection-timeout: 10000
DataSourceConfig+Mybatis 分包配置
db1
@Configuration
@MapperScan(basePackages = "com.lcx.more.mapper.db1", sqlSessionFactoryRef = "db1SqlSessionFactory")
public class DB1Config {
@Bean("coolSourceDataSource")
@ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.primary")
public DataSource primaryDataSource() {
return new AtomikosDataSourceBean();
}
@Bean(name = "db1SqlSessionFactory")
public SqlSessionFactory db1SqlSessionFactory(@Qualifier("coolSourceDataSource") DataSource coolSourceDataSource) throws Exception {
MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean ();
sessionFactory.setDataSource(coolSourceDataSource);
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setMapUnderscoreToCamelCase(true);//驼峰
sessionFactory.setConfiguration(configuration);
sessionFactory.setTypeAliasesPackage("com.lcx.more.entity.db1");
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath*:mapper/db1/*.xml"));
return sessionFactory.getObject();
}
@Bean(name = "db1SqlSessionTemplate")
public SqlSessionTemplate db1SqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
db2
@Configuration
@MapperScan(basePackages = "com.lcx.more.mapper.db2", sqlSessionFactoryRef = "db2SqlSessionFactory")
public class DB2Config {
@Bean("coolUserDataSource")
@ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.secondary")
public DataSource secondaryDataSource() {
return new AtomikosDataSourceBean();
}
@Bean(name = "db2SqlSessionFactory")
public SqlSessionFactory db2SqlSessionFactory(@Qualifier("coolUserDataSource") DataSource coolUserDataSource) throws Exception {
MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean ();
sessionFactory.setDataSource(coolUserDataSource);
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setMapUnderscoreToCamelCase(true);//驼峰
sessionFactory.setConfiguration(configuration);
sessionFactory.setTypeAliasesPackage("com.lcx.more.entity.db2");
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath*:mapper/db2/*.xml"));
return sessionFactory.getObject();
}
@Bean(name = "db2SqlSessionTemplate")
public SqlSessionTemplate db2SqlSessionTemplate(@Qualifier("db2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
测试
@Transactional(rollbackFor = Exception.class)
public void jtaTest() {
// DB1
TxJTATest txJTATest = new TxJTATest();
txJTATest.setName("test2");
txJTATestMapper.insert(txJTATest);
// DB2 tb1
TestTxA testTxA = new TestTxA();
testTxA.setTestName("txa2");
testTxAMapper.insert(testTxA);
// DB2 tb2
TestTxB testTxB = new TestTxB();
testTxB.setTestCode("txb2");
testTxBMapper.insert(testTxB);
throw new RuntimeException("报错啦...");
}