work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

分布式事务基本概念可参考分布式事务介绍

这里我们介绍Atomikos分布式事务,它是基于XA的分布式事务

 

1、准备-创建数据库

 

 在192.168.127.129和192.168.127.134分别创建数据库xa_129和xa_134, 表分别为xa_129, xa_134, 表结构都是id和name。

 

2、创建工程

1) 创建Spring Boot工程

 

 

命名为my-xa-demo

 

 选择需要的依赖后点击完成

 

 

 

3、添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

 

 

4、使用MyBatis-generator生成数据库相关的文件

 

 

 

 

5、配置数据源

 1)  ConfigDb129 

/**
 * 数据源配置。RM资源管理器
 */
@Configuration  
@MapperScan(value = "com.example.myxademo.db129.dao", sqlSessionFactoryRef = "sqlSessionFactoryBean129")
public class ConfigDb129 {

    @Bean("db129")
    public DataSource db129(){
        MysqlXADataSource xaDs = new MysqlXADataSource();
        xaDs.setUser("root");
        xaDs.setPassword("123456");
        xaDs.setUrl("jdbc:mysql://192.168.127.129:3306/xa_129");

        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(xaDs);
        atomikosDataSourceBean.setUniqueResourceName("db129");
        return  atomikosDataSourceBean;
    }

    @Bean("sqlSessionFactoryBean129")
    public SqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("db129") DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        ResourcePatternResolver resourcePatternResolver  = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resourcePatternResolver.getResources("mybatis/db129/*.xml"));
        return  sqlSessionFactoryBean;
    }

    /**
     * JTA 事务管理器
     * @return
     */
    @Bean("xaTransaction")
    public JtaTransactionManager jtaTransactionManager(){
        UserTransaction userTransaction = new UserTransactionImp();
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        return  new JtaTransactionManager(userTransaction, userTransactionManager);
    }
}

 并且定义了事务管理器

 

 

 ConfigDb134 

/**
 * 数据源配置。RM资源管理器
 */
@Configuration
@MapperScan(value = "com.example.myxademo.db134.dao", sqlSessionFactoryRef = "sqlSessionFactoryBean134")
public class ConfigDb134 {

    @Bean("db134")
    public DataSource db134(){
        MysqlXADataSource xaDs = new MysqlXADataSource();
        xaDs.setUser("root");
        xaDs.setPassword("123456");
        xaDs.setUrl("jdbc:mysql://192.168.127.134:3306/xa_134");


        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setUniqueResourceName("db134");
        atomikosDataSourceBean.setXaDataSource(xaDs);
        return  atomikosDataSourceBean;
    }

    @Bean("sqlSessionFactoryBean134")
    public SqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("db134") DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        ResourcePatternResolver resourcePatternResolver  = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resourcePatternResolver.getResources("mybatis/db134/*.xml"));
        return  sqlSessionFactoryBean;
    }
}

  

 

 6、创建服务

@Service
public class XAService {

    @Resource
    private XA129Mapper xa129Mapper;

    @Resource
    private XA134Mapper xa134Mapper;

    @Transactional(transactionManager = "xaTransaction")
    public void testXA(){
        XA129 xa129 = new XA129();
        xa129.setId(1);
        xa129.setName("XA_129");
        xa129Mapper.insert(xa129);

        XA134 xa134 = new XA134();
        xa134.setId(1);
        xa134.setName("XA_134");
        xa134Mapper.insert(xa134);

    }
}

  

7、测试

@SpringBootTest
class MyXaDemoApplicationTests {


    @Test
    void testXA() {
        xaService.testXA();
    }

}

  运行后,可以发现两个数据库多插入成功了。

 

 

 

 

8、模拟事务回滚

将两个表的数据清空,并且修改name字段的长度为1,重新运行测试

 

 

可以发现,两个表都没有插入成功。