JTA+Atomikos解决分布式事务问题

JTA分布式事务:Java Transaction API,允许应用程序执行分布式事务处理。

Atomikos:为java平台提供增值服务并且开源的事务管理器。

基于xa协议,xa协议是以两阶段提交协议为基础的。

这种处理方案一般是针对传统架构项目的分布式事务,不适合用在微服务架构中。

 

 

下面是springboot配置多个oracle数据源,重现分布式事务问题的例子

一、添加依赖

        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.4</version>
        </dependency>
        <!-- 这里使用的是JPA包,也可使用JDBC包进行 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

由于maven仓库没有ojdbc6,需要自行下载安装

 

二、修改application.yml配置文件

spring:
  jpa:
    database: oracle
    show-sql: true
  datasource:
    master:
      jdbc-url: jdbc:oracle:thin:@127.0.0.1:1521:ORCL
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: oracle.jdbc.driver.OracleDriver
      username: wx
      password: 123
    slave1:
      jdbc-url: jdbc:oracle:thin:@127.0.0.1:1521:ORCL
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: oracle.jdbc.driver.OracleDriver
      username: wl
      password: 123456

 

三、创建数据源配置文件

@Configuration
public class DataSourceConfig {

    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource dataSource1(){
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.slave1")
    public DataSource dataSource2(){
        return DataSourceBuilder.create().build();
    }
}

@Primary注释表示这个数据源是默认数据源,如果没有这个注释的话,开启事务的时候会报错

 

四、创建JdbcTemplate配置类


@Configuration
public class JdbcTemplateConfig {

    @Bean
    public JdbcTemplate template1(@Qualifier("dataSource1")DataSource dataSource1){
        return new JdbcTemplate(dataSource1);
    }

    @Bean
    public JdbcTemplate template2(@Qualifier("dataSource2")DataSource dataSource2){
        return new JdbcTemplate(dataSource2);
    }
}

 

五、使用测试类进行测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class JtaatomikosApplicationTests {
    @Autowired
    private JdbcTemplate template1;
    @Autowired
    private JdbcTemplate template2;

    @Test
    @Transactional
    public void contextLoads() {
        String sql = "INSERT INTO \"test\" VALUES('asd','张三','24')";
        template1.update(sql);
        template2.update(sql);
        int i = 1/0;
    }

}

test表只有三个字段:id,name,age

表里边数据都是空的。

执行测试方法contextLoads

控制台会抛异常

此时去数据库查看数据会发现

WL数据库插入数据成功了。

WX数据库插入数据失败了。

 

WX数据库是主数据源,说明主数据源事务回滚成功了,但是副数据源事务没有回滚,这就是分布式事务问题。

 

 

 

为了解决这个问题,我们引入atomikos解决

在原来的项目基础上,添加依赖

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

 

修改数据源配置文件

@Configuration
public class DataSourceConfig {

    @Bean
    public DataSource dataSource1(){
        Properties properties = new Properties();
        properties.setProperty("URL","jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
        properties.setProperty("user","wx");
        properties.setProperty("password","123");
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaProperties(properties);
        atomikosDataSourceBean.setUniqueResourceName("dataSource1");
        atomikosDataSourceBean.setXaDataSourceClassName("oracle.jdbc.xa.client.OracleXADataSource");
        return atomikosDataSourceBean;
    }

    @Bean
    public DataSource dataSource2(){
        Properties properties = new Properties();
        properties.setProperty("URL","jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
        properties.setProperty("user","wl");
        properties.setProperty("password","123456");
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaProperties(properties);
        atomikosDataSourceBean.setUniqueResourceName("dataSource2");
        atomikosDataSourceBean.setXaDataSourceClassName("oracle.jdbc.xa.client.OracleXADataSource");
        return atomikosDataSourceBean;
    }
}

可以发现,我们去掉了@Primary和@ConfigurationProperties注释,手动设置数据库参数,将数据源类型改成了AtomikoDataSourceBean类型,这个类型的数据源需要添加XADataSource类型的数据源参数,这里我们添加的是OracleXADataSource,这个类就是JTA类型的。

现在我们就已经把事务交给引入进来的全局事务协调了。

执行测试方法contextLoads

可以发现控制台同样抛出/ by zero异常,WX和WL数据库都没有插入数据,说明都进行事务回滚了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值