Distributed things [XA strong consistency distributed transaction practice, Seata provides XA mode to implement distributed transactions] Multi-data source configuration

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);
   }
}