Springboot + JTA 简单实现多数据源事务
- JTA
- 依赖
- YML配置
- DataSourceConfig+Mybatis 分包配置
- db1
- db2
- 测试
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-8user: ENC(leNmW2mZWHadQdE9aq5iIw==)password: ENC(k5SFNga7adQ/xFsxzbe3Rbe3pZEow0KdSj0pWlDjDJA=)xa-data-source-class-name: com.mysql.cj.jdbc.MysqlXADataSourceunique-resource-name: coolSourcemax-pool-size: 25min-pool-size: 3max-lifetime: 20000borrow-connection-timeout: 10000secondary:xa-properties:url: jdbc:mysql://host:3306/test-user?useUnicode=true&characterEncoding=utf-8user: ENC(leNmW2mZWHadQdE9aq5iIw==)password: ENC(k5SFNga7adQ/xFsxzbe3Rbe3pZEow0KdSj0pWlDjDJA=)xa-data-source-class-name: com.mysql.cj.jdbc.MysqlXADataSourceunique-resource-name: coolUsermax-pool-size: 25min-pool-size: 3max-lifetime: 20000borrow-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() {// DB1TxJTATest txJTATest = new TxJTATest();txJTATest.setName("test2");txJTATestMapper.insert(txJTATest);// DB2 tb1TestTxA testTxA = new TestTxA();testTxA.setTestName("txa2");testTxAMapper.insert(testTxA);// DB2 tb2TestTxB testTxB = new TestTxB();testTxB.setTestCode("txb2");testTxBMapper.insert(testTxB);throw new RuntimeException("报错啦...");}