Reprint: https://mp.weixin.qq.com/s/1_xxMi9WPhHaMdcIc2H7pA
-- Note that 0.3.0 + adds unique index ux_undo_log here CREATE TABLE `undo_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `branch_id` bigint(20) NOT NULL, `xid` varchar(100) NOT NULL, `context` varchar(128) NOT NULL, `rollback_info` longblob NOT NULL, `log_status` int(11) NOT NULL, `log_created` datetime NOT NULL, `log_modified` datetime NOT NULL, `ext` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency>
seata: # Registration Center registry: type: file service: # The address and port information of the seata server. Use English semicolons to separate multiple ones. grouplist: default: 192.168.66.100:9999 tx-service-group: my_test_tx_group
DROP TABLE IF EXISTS `user_account`; CREATE TABLE `user_account` ( `account_no` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'account number' , `account_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'account name' , `account_balance` decimal(10, 2) NULL DEFAULT NULL COMMENT 'Account Balance' , PRIMARY KEY (`account_no`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
INSERT INTO `user_account` VALUES ('1001','Zhang San', 10000.00);
INSERT INTO `user_account` VALUES ('1002','李思', 10000.00);
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jta-atomikos</artifactId> </dependency> <!-- druid connection pool dependent components --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.22</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
server: port: 6003 spring: autoconfigure: #Disable automatic configuration of druid connection pool exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure datasource: #Choose druid's XADataSource data source because this data source supports distributed transaction management type: com.alibaba.druid.pool.xa.DruidXADataSource #The following are custom fields dynamic: primary:master datasource: master: url: jdbc:mysql://192.168.66.102:3306/tx-xa-01? useUnicode=true & amp;characterEncoding=utf8 & amp;allowMultiQueries=true & amp;useSSL=false & amp;zeroDateTimeBehavior=convertToNull & amp;serverTimezone=Asia/Shanghai & amp;autoReconnect=true username: root password01: 123456 driver-class-name: com.mysql.jdbc.Driver slave: url: jdbc:mysql://192.168.66.102:3306/tx-xa-02?useUnicode=true & amp;characterEncoding=utf8 & amp;allowMultiQueries=true & amp;useSSL=false & amp;zeroDateTimeBehavior=convertToNull & amp; serverTimezone=Asia/Shanghai & amp;autoReconnect=true username: root password01: 123456 driver-class-name: com.mysql.jdbc.Driver validation-query: SELCET 1
Write the main startup class @Slf4j @SpringBootApplication @EnableTransactionManagement(proxyTargetClass = true) public class TxXaStarter {<!-- --> public static void main(String[] args){<!-- --> SpringApplication.run(TxXaStarter.class,args); log.info("****************** TxXaStarter**********"); } }
@Data @ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.master") public class DBConfig1 {<!-- --> private String url; private String username; private String password; private String dataSourceClassName; }
@Data @ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.slave") public class DBConfig2 {<!-- --> private String url; private String username; private String password; private String dataSourceClassName; }
public interface UserAccount1Mapper extends BaseMapper<UserAccount> {<!-- -->} public interface UserAccount2Mapper extends BaseMapper<UserAccount> {<!-- -->}
@Configuration @MapperScan(basePackages = "com.tong.mapper1", sqlSessionTemplateRef = "masterSqlSessionTemplate") public class MyBatisConfig1 {<!-- --> @Bean(name = "masterDataSource") public DataSource masterDataSource(DBConfig1 dbConfig1) {<!-- --> AtomikosDataSourceBean sourceBean = new AtomikosDataSourceBean(); sourceBean.setUniqueResourceName("masterDataSource"); sourceBean.setXaDataSourceClassName(dbConfig1.getDataSourceClassName()); sourceBean.setTestQuery("select 1"); sourceBean.setBorrowConnectionTimeout(3); MysqlXADataSource dataSource = new MysqlXADataSource(); dataSource.setUser(dbConfig1.getUsername()); dataSource.setPassword(dbConfig1.getPassword()); dataSource.setUrl(dbConfig1.getUrl()); sourceBean.setXaDataSource(dataSource); return sourceBean; } @Bean(name = "masterSqlSessionFactory") public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {<!-- --> MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); return sqlSessionFactoryBean.getObject(); } @Bean(name = "masterSqlSessionTemplate") public SqlSessionTemplate masterSqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory){<!-- --> return new SqlSessionTemplate(sqlSessionFactory); } }
@Configuration @MapperScan(basePackages = "com.tong.mapper2", sqlSessionTemplateRef = "slaveSqlSessionTemplate") public class MyBatisConfig2 {<!-- --> @Bean(name = "slaveDataSource") public DataSource slaveDataSource(DBConfig2 dbConfig2) {<!-- --> AtomikosDataSourceBean sourceBean = new AtomikosDataSourceBean(); sourceBean.setUniqueResourceName("slaveDataSource"); sourceBean.setXaDataSourceClassName(dbConfig2.getDataSourceClassName()); sourceBean.setTestQuery("select 1"); sourceBean.setBorrowConnectionTimeout(3); MysqlXADataSource dataSource = new MysqlXADataSource(); dataSource.setUser(dbConfig2.getUsername()); dataSource.setPassword(dbConfig2.getPassword()); dataSource.setUrl(dbConfig2.getUrl()); sourceBean.setXaDataSource(dataSource); return sourceBean; } @Bean(name = "slaveSqlSessionFactory") public SqlSessionFactory slaveSqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception {<!-- --> MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); return sqlSessionFactoryBean.getObject(); } @Bean(name = "slaveSqlSessionTemplate") public SqlSessionTemplate slaveSqlSessionTemplate(@Qualifier("slaveSqlSessionFactory") SqlSessionFactory sqlSessionFactory){<!-- --> return new SqlSessionTemplate(sqlSessionFactory); } }