jta-atomikos实现多数据源事务案例

 1、pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>
        <!-- mybatis-plus启动器 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- atomikos实现跨库事务 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
        </dependency>
    </dependencies>

2、yml文件配置

server:
  port: 5053
spring:
  application:
    name: atomikos-service
mysql:
  datasource:
    test1:
      url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
      minPoolSize: 5
      maxPoolSize: 20
      maxLifetime: 20000
      borrowConnectionTimeout: 30000
      loginTimeout: 30
      maintenanceInterval: 60
      maxIdleTime: 60
    test2:
      url: jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
      minPoolSize: 5
      maxPoolSize: 20
      maxLifetime: 20000
      borrowConnectionTimeout: 30000
      loginTimeout: 30
      maintenanceInterval: 60
      maxIdleTime: 60
# 日志级别
logging:
  level:
    root: info

3、数据库

create database test1;
use test1;
create table employee(
    id int primary key auto_increment,
    emp_name varchar(20) not null
);

create database test2;
use test2;
create table department(
    id int primary key auto_increment,
    name varchar(20) not null
);

select * from test1.employee;

select * from  test2.department;

4、配置类

package com.bilibili.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "mysql.datasource.test1")
public class DBProperties1 {

    private String url;
    private String username;
    private String password;
    private String driverClassName;
    private int minPoolSize;
    private int maxPoolSize;
    private int maxLifetime;
    private int borrowConnectionTimeout;
    private int loginTimeout;
    private int maintenanceInterval;
    private int maxIdleTime;
    private String testQuery;
}
package com.bilibili.config;

import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.mysql.cj.jdbc.MysqlXADataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.sql.SQLException;

@Configuration
@MapperScan(basePackages = "com.bilibili.mapper1",sqlSessionFactoryRef = "test1SqlSessionFactory")
public class DBConfig1 {


    @Autowired
    private DBProperties1 dbProperties1;

    @Bean(name = "test1DataSource")
    public DataSource testDataSource() {
        MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
        mysqlXADataSource.setUrl(dbProperties1.getUrl());
        mysqlXADataSource.setUser(dbProperties1.getUsername());
        mysqlXADataSource.setPassword(dbProperties1.getPassword());
        try {
            mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(mysqlXADataSource);
        atomikosDataSourceBean.setUniqueResourceName("test1DataSource");
        atomikosDataSourceBean.setMinPoolSize(dbProperties1.getMinPoolSize());
        atomikosDataSourceBean.setMaxPoolSize(dbProperties1.getMaxPoolSize());
        atomikosDataSourceBean.setBorrowConnectionTimeout(dbProperties1.getBorrowConnectionTimeout());
        try {
            atomikosDataSourceBean.setLoginTimeout(dbProperties1.getLoginTimeout());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        atomikosDataSourceBean.setMaintenanceInterval(dbProperties1.getMaintenanceInterval());
        atomikosDataSourceBean.setMaxIdleTime(dbProperties1.getMaxIdleTime());
        atomikosDataSourceBean.setTestQuery(dbProperties1.getTestQuery());
        return atomikosDataSourceBean;
    }


    @Bean(name = "test1SqlSessionFactory")
    public SqlSessionFactory test1SessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = "test1SqlSessionTemplate")
    public SqlSessionTemplate test1SqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
package com.bilibili.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "mysql.datasource.test2")
public class DBProperties2 {

    private String url;
    private String username;
    private String password;
    private String driverClassName;
    private int minPoolSize;
    private int maxPoolSize;
    private int borrowConnectionTimeout;
    private int loginTimeout;
    private int maintenanceInterval;
    private int maxIdleTime;
    private String testQuery;
}
package com.bilibili.config;

import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.mysql.cj.jdbc.MysqlXADataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.sql.SQLException;

@Configuration
@MapperScan(basePackages = "com.bilibili.mapper2",sqlSessionFactoryRef = "test2SqlSessionFactory")
public class DBConfig2 {

    @Autowired
    private DBProperties2 dbProperties2;

    @Bean(name = "test2DataSource")
    public DataSource testDataSource() {
        MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
        mysqlXADataSource.setUrl(dbProperties2.getUrl());
        mysqlXADataSource.setUser(dbProperties2.getUsername());
        mysqlXADataSource.setPassword(dbProperties2.getPassword());
        try {
            mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(mysqlXADataSource);
        atomikosDataSourceBean.setUniqueResourceName("test2DataSource");
        atomikosDataSourceBean.setMinPoolSize(dbProperties2.getMinPoolSize());
        atomikosDataSourceBean.setMaxPoolSize(dbProperties2.getMaxPoolSize());
        atomikosDataSourceBean.setBorrowConnectionTimeout(dbProperties2.getBorrowConnectionTimeout());
        try {
            atomikosDataSourceBean.setLoginTimeout(dbProperties2.getLoginTimeout());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        atomikosDataSourceBean.setMaintenanceInterval(dbProperties2.getMaintenanceInterval());
        atomikosDataSourceBean.setMaxIdleTime(dbProperties2.getMaxIdleTime());
        atomikosDataSourceBean.setTestQuery(dbProperties2.getTestQuery());
        return atomikosDataSourceBean;
    }


    @Bean(name = "test2SqlSessionFactory")
    public SqlSessionFactory test2SessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = "test2SqlSessionTemplate")
    public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

5、实体类

package com.bilibili.entity1;

import lombok.Data;

@Data
public class Employee {
    private Integer id;
    private String empName;
}
package com.bilibili.entity2;

import lombok.Data;

@Data
public class Department {

    private Integer id;

    private String name;
}

6、Mapper 接口

package com.bilibili.mapper1;

import com.bilibili.entity1.Employee;
import org.apache.ibatis.annotations.Insert;

public interface EmployeeMapper {

    @Insert("insert into employee(emp_name) values(#{empName})")
    int insertEmp(Employee employee);
}
package com.bilibili.mapper2;

import com.bilibili.entity2.Department;
import org.apache.ibatis.annotations.Insert;

public interface DepartmentMapper {

    @Insert("insert into department(name) values(#{name})")
    int insertDept(Department department);
}

7、业务类

package com.bilibili.service;

public interface TestService {
    void test();
}
package com.bilibili.service.impl;

import com.bilibili.entity1.Employee;
import com.bilibili.entity2.Department;
import com.bilibili.mapper1.EmployeeMapper;
import com.bilibili.mapper2.DepartmentMapper;
import com.bilibili.service.TestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.TransactionManager;
import javax.transaction.Transactional;

@Slf4j
@Service
public class TestServiceImpl implements TestService {

    @Autowired
    private TransactionManager transationManager;

    @Autowired
    private EmployeeMapper employeeMapper;
    @Autowired
    private DepartmentMapper departmentMapper;

    @Transactional(rollbackOn = Exception.class)
    @Override
    public void test() {
//        JtaTransactionManager jtaTransactionManager = (JtaTransactionManager) transationManager;
//        UserTransaction userTransaction = jtaTransactionManager.getUserTransaction();
//        log.info("===============userTransaction:{}", userTransaction);
        Employee employee = new Employee();
        employee.setEmpName("tom");
        Department department = new Department();
        department.setName("deptName");

        employeeMapper.insertEmp(employee);
        departmentMapper.insertDept(department);
//        int i = 1 / 0;
    }
}

8、启动类

@SpringBootApplication(scanBasePackages = {"com.bilibili"})
public class AtomikosApplication {
    public static void main(String[] args) {
        SpringApplication.run(AtomikosApplication.class, args);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值