springboot-atomikos多数据源分布式事务

atomikos应用场景:单应用多数据源

引入依赖

<dependency>
	<groupId>org.springframework.bootgroupId>
	<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
	<groupId>org.springframework.bootgroupId>
	<artifactId>spring-boot-starter-jta-atomikosartifactId>
dependency>
<dependency>
	<groupId>org.mybatis.spring.bootgroupId>
	<artifactId>mybatis-spring-boot-starterartifactId>
	<version>2.0.1version>
dependency>

<dependency>
	<groupId>com.alibabagroupId>
	<artifactId>druidartifactId>
	<version>1.1.14version>
dependency>

<dependency>
	<groupId>mysqlgroupId>
	<artifactId>mysql-connector-javaartifactId>
	<scope>runtimescope>
dependency>

<dependency>
	<groupId>org.projectlombokgroupId>
	<artifactId>lombokartifactId>
	<optional>trueoptional>
dependency>
<dependency>
	<groupId>org.springframework.bootgroupId>
	<artifactId>spring-boot-starter-testartifactId>
	<scope>testscope>
dependency>

修改配置文件

spring:
  datasource:
    #使用druid连接池
    druid:
      #数据源1的名称
      one:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://192.168.211.128:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: root
        password: root
      #数据源2的名称
      two:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://192.168.211.129:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: root
        password: root

配置数据源

只需要配置数据源即可,全局事务管理器(JtaTransactionManager)由spring自动配置

@Configuration
public class DataSourceConfig {

    /**
     * 创建Druid的XA连接池
     * @return
     */
    @Bean
    @ConfigurationProperties("spring.datasource.druid.one")
    public XADataSource druidXADataSource1(){
        return new DruidXADataSource();
    }

    /**
     * 创建Atomikos数据源
     * 注解@DependsOn("druidXADataSource1"),在名为druidXADataSource1的bean实例化后加载当前bean
     * @param xaDataSource
     * @return
     */
    @Bean
    @DependsOn("druidXADataSource1")
    @Primary
    public DataSource dataSource1(@Qualifier("druidXADataSource1") XADataSource xaDataSource) {
        //这里的AtomikosDataSourceBean使用的是spring提供的
        AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
        dataSource.setXaDataSource(xaDataSource);
        return dataSource;
    }


    @Bean
    @ConfigurationProperties("spring.datasource.druid.two")
    public XADataSource druidXADataSource2(){
        return new DruidXADataSource();
    }

    @Bean
    @DependsOn("druidXADataSource2")
    public DataSource dataSource2(@Qualifier("druidXADataSource2") XADataSource xaDataSource) {
        AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
        dataSource.setXaDataSource(xaDataSource);
        return dataSource;
    }
}

配置mybatis

如果使用其他的orm框架,自行配置。
数据源2的mybatis配置和下面代码相似,去除@Primary注解,修改配置属性即可。

@Configuration
//指定扫描的dao包和SqlSession实例
@MapperScan(basePackages = "demo.springboot.atomikos.dao1", sqlSessionTemplateRef = "sessionTemplate1")
public class Mybatis1Config {

    /**
     * SqlSessionFactory
     *
     * @param dataSource
     * @return
     * @throws Exception
     */
    @Bean
    @Primary
    public SqlSessionFactory sqlSessionFactory1(@Qualifier("dataSource1") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        //mapper文件位置
//        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/one/*.xml"));
        return bean.getObject();
    }

    /**
     * SqlSession实例
     *
     * @param sqlSessionFactory
     * @return
     */
    @Bean
    @Primary
    public SqlSessionTemplate sessionTemplate1(@Qualifier("sqlSessionFactory1") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

DAO

public interface UserDAO1 {

    @Update("update user set name = #{name} where id = #{id}")
    int updateById(@Param("name")String name, @Param("id")Long id);
}

public interface UserDAO2 {

    @Update("update user set name = #{name} where id = #{id}")
    int updateById(@Param("name")String name, @Param("id")Long id);
}

service

@Service
public class TestService {
    @Autowired
    private UserDAO1 userDAO1;
    @Autowired
    private UserDAO2 userDAO2;

 	/**
     * 在需要事务的方法加上@Transactional注解即可
     */
    @Transactional
    public void test(){
        userDAO1.updateById("haha", 1L);
        userDAO2.updateById("hehe", 2L);
        //模拟异常
        int a = 1/0;
    }
}

测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class AtomikosApplicationTests {

    @Autowired
    private TestService testService;

    @Test
    public void test() {
        testService.test();
    }

}

数据源1中的User{“id”:1,“name”:“张三”}
数据源2中的User{“id”:2,name:“李四”}
运行测试出现异常后,两个数据库都回滚了,数据未改变

项目路径


作者博客

作者公众号
在这里插入图片描述

你可能感兴趣的:(分布式事务,springboot,atomikos,分布式事务)