Spring boot + atomikos 多数据源处理及事物处理

1.pom文件

<dependency>
    <groupId>com.atomikos</groupId>
    <artifactId>transactions</artifactId>
    <version>4.0.6</version>
</dependency>
<dependency>
    <groupId>com.atomikos</groupId>
    <artifactId>transactions-api</artifactId>
    <version>4.0.6</version>
</dependency>
<dependency>
    <groupId>com.atomikos</groupId>
    <artifactId>transactions-jta</artifactId>
    <version>4.0.6</version>
</dependency>
<dependency>
    <groupId>com.atomikos</groupId>
    <artifactId>transactions-jdbc</artifactId>
    <version>4.0.6</version>
</dependency>
<dependency>
    <groupId>com.atomikos</groupId>
    <artifactId>atomikos-util</artifactId>
    <version>4.0.6</version>
</dependency>

<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>javax.transaction-api</artifactId>
    <version>1.2</version>
</dependency>

2. aplication.properties

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql:///test2?useUnicode=true&useSSL=false&characterEncoding=utf8
spring.datasource.username=xxxx
spring.datasource.password=xxxxx
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#ds1,ds2 其他两个数据源
slave.datasource.names=ds1,ds2
#ds1
slave.datasource.ds1.driver=com.mysql.jdbc.Driver
slave.datasource.ds1.url=jdbc:mysql:///lottery?useUnicode=true&useSSL=false&characterEncoding=utf8
slave.datasource.ds1.username=xxxxx
slave.datasource.ds1.password=xxxxx
#ds2
slave.datasource.ds2.driver=com.mysql.jdbc.Driver
slave.datasource.ds2.url=jdbc:mysql://localhost:3306/test?useUnicode=true&useSSL=false&characterEncoding=utf8
slave.datasource.ds2.username=root
slave.datasource.ds2.password=root

3.DbConfig 实体类

import java.io.Serializable;

@Data
public class DbConfig implements Serializable{
   private static final long serialVersionUID = 1L;
   private String url;
   private String username;
   private String password;

}

4. 配置数据源 DataSourceConfig 链接主库

package com.spf.boot.atomikos.db;

import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.mysql.jdbc.jdbc2.optional.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.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import javax.sql.DataSource;

/**
 * atomikos 分布式数据源
 */
@Configuration
@MapperScan(basePackages = {"com.spf.boot.mapper.ds"}, sqlSessionTemplateRef = "masterSqlSessionTemplate")
public class DataSourceConfig {

    @Bean("dbConfig")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DbConfig getDbConfig() {
        return new DbConfig();
    }

    //**************************************************************************************************************************************************
    //配置数据源
    @Primary
    @Bean(name="datasource")
    public DataSource Datasource(@Qualifier("dbConfig") DbConfig config1) {
        MysqlXADataSource mysqlXADataSource=new MysqlXADataSource();
        mysqlXADataSource.setUrl(config1.getUrl());
        mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
        mysqlXADataSource.setPassword(config1.getPassword());
        mysqlXADataSource.setUser(config1.getUsername());

        AtomikosDataSourceBean atomikosDataSourceBean=new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(mysqlXADataSource);
        atomikosDataSourceBean.setUniqueResourceName("datasource");

//    atomikosDataSourceBean.setMinPoolSize(config1.getMinPoolSize());
//    atomikosDataSourceBean.setMaxPoolSize(config1.getMaxPoolSize());
//    atomikosDataSourceBean.setMaxLifetime(config1.getMaxLifetime());
//    atomikosDataSourceBean.setBorrowConnectionTimeout(config1.getBorrowConnectionTimeout());
//    atomikosDataSourceBean.setLoginTimeout(config1.getLoginTimeout());
//    atomikosDataSourceBean.setMaintenanceInterval(config1.getMaintenanceInterval());
//    atomikosDataSourceBean.setMaxIdleTime(config1.getMaxIdleTime());
        return atomikosDataSourceBean;
    }

    //**************************************************************************************************************************************************

// @Bean(name="primaryJdbcTemplate")
// public JdbcTemplate primaryJdbcTemplate(@Qualifier("datasource")DataSource dataSource) {
//    return new JdbcTemplate(dataSource);
// }

    @Bean(name = "sqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("datasource")DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        //添加XML目录
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mybatis/xml/*Mapper.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = "masterSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

5. 配置从库数据链接 DataDs1Source 

package com.spf.boot.atomikos.db;

import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.mysql.jdbc.jdbc2.optional.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.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.io.IOException;

/**
 * @author ShuPF
 * @类说明:
 * @date 2018-12-27 14:42
 */
@Configuration
@MapperScan(basePackages = {"com.spf.boot.mapper.ds1"}, sqlSessionTemplateRef = "ds1SqlSessionTemplate")
public class DataDs1Source {

    @Bean("db1Config")
    @ConfigurationProperties(prefix = "slave.datasource.ds1")
    public DbConfig getDb2Config() {
        return new DbConfig();
    }

    //配置数据源
    @Bean(name="datasourceDs1")
    public DataSource datasourceDs1(@Qualifier("db1Config") DbConfig config1) {
        MysqlXADataSource mysqlXADataSource=new MysqlXADataSource();
        mysqlXADataSource.setUrl(config1.getUrl());
        mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
        mysqlXADataSource.setPassword(config1.getPassword());
        mysqlXADataSource.setUser(config1.getUsername());

        AtomikosDataSourceBean atomikosDataSourceBean=new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(mysqlXADataSource);
        atomikosDataSourceBean.setUniqueResourceName("datasourceDs1");

//    atomikosDataSourceBean.setMinPoolSize(config1.getMinPoolSize());
//    atomikosDataSourceBean.setMaxPoolSize(config1.getMaxPoolSize());
//    atomikosDataSourceBean.setMaxLifetime(config1.getMaxLifetime());
//    atomikosDataSourceBean.setBorrowConnectionTimeout(config1.getBorrowConnectionTimeout());
//    atomikosDataSourceBean.setLoginTimeout(config1.getLoginTimeout());
//    atomikosDataSourceBean.setMaintenanceInterval(config1.getMaintenanceInterval());
//    atomikosDataSourceBean.setMaxIdleTime(config1.getMaxIdleTime());
        return atomikosDataSourceBean;
    }

//    @Bean(name="ds1JdbcTemplate")
//    public JdbcTemplate ds1JdbcTemplate(@Qualifier("datasourceDs1")DataSource dataSource) {
//        return new JdbcTemplate(dataSource);
//    }

    @Bean(name = "ds1SqlSessionFactory")
    public SqlSessionFactory ds1SqlSessionFactory(@Qualifier("datasourceDs1")DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        //添加XML目录
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mybatis/xml/*Mapper.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = "ds1SqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("ds1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

6. DataDs2Source

package com.spf.boot.atomikos.db;

import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.mysql.jdbc.jdbc2.optional.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.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

/**
 * @author ShuPF
 * @类说明:
 * @date 2018-12-27 14:42
 */
@Configuration
@MapperScan(basePackages = {"com.spf.boot.mapper.ds2"}, sqlSessionTemplateRef = "ds2SqlSessionTemplate")
public class DataDs2Source {

    @Bean("db2Config")
    @ConfigurationProperties(prefix = "slave.datasource.ds2")
    public DbConfig getDb3Config() {
        return new DbConfig();
    }


    //配置数据源
    @Bean(name="datasourceDs2")
    public DataSource datasourceDs2(@Qualifier("db2Config") DbConfig config1) {
        MysqlXADataSource mysqlXADataSource=new MysqlXADataSource();
        mysqlXADataSource.setUrl(config1.getUrl());
        mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
        mysqlXADataSource.setPassword(config1.getPassword());
        mysqlXADataSource.setUser(config1.getUsername());

        AtomikosDataSourceBean atomikosDataSourceBean=new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(mysqlXADataSource);
        atomikosDataSourceBean.setUniqueResourceName("datasourceDs2");

//    atomikosDataSourceBean.setMinPoolSize(config1.getMinPoolSize());
//    atomikosDataSourceBean.setMaxPoolSize(config1.getMaxPoolSize());
//    atomikosDataSourceBean.setMaxLifetime(config1.getMaxLifetime());
//    atomikosDataSourceBean.setBorrowConnectionTimeout(config1.getBorrowConnectionTimeout());
//    atomikosDataSourceBean.setLoginTimeout(config1.getLoginTimeout());
//    atomikosDataSourceBean.setMaintenanceInterval(config1.getMaintenanceInterval());
//    atomikosDataSourceBean.setMaxIdleTime(config1.getMaxIdleTime());
        return atomikosDataSourceBean;
    }


//    @Bean(name="ds2JdbcTemplate")
//    public JdbcTemplate ds2JdbcTemplate(@Qualifier("datasourceDs2")DataSource dataSource) {
//        return new JdbcTemplate(dataSource);
//    }

    @Bean(name = "ds2SqlSessionFactory")
    public SqlSessionFactory ds2SqlSessionFactory(@Qualifier("datasourceDs2")DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        //添加XML目录
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mybatis/xml/*Mapper.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = "ds2SqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("ds2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

7. 配置多数据源事物的处理

package com.spf.boot.atomikos;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import org.springframework.transaction.jta.JtaTransactionManager;

import javax.transaction.SystemException;
import java.util.Properties;

/***
 *  分布式事物管理
 */
@Configuration
public class AutoProxyRegist {

    @Bean(name="atomikosTransactionManager",initMethod="init",destroyMethod="close")
    public UserTransactionManager userTransactionManager(){
        UserTransactionManager transactionManager = new UserTransactionManager();
        transactionManager.setForceShutdown(false);
        return transactionManager;
    }

    @Bean(name="atomikosUserTransaction")
    public UserTransactionImp userTransactionImp() throws SystemException {
        UserTransactionImp transactionImp = new UserTransactionImp();
        transactionImp.setTransactionTimeout(120);
        return transactionImp;
    }

    @Bean("springTransactionManager")
    public JtaTransactionManager transactionManager(
            @Qualifier("atomikosTransactionManager") UserTransactionManager transactionManager,
            @Qualifier("atomikosUserTransaction") UserTransactionImp userTransaction) {
        JtaTransactionManager jtaTM = new JtaTransactionManager();
        jtaTM.setTransactionManager(transactionManager);
        jtaTM.setUserTransaction(userTransaction);
        jtaTM.setAllowCustomIsolationLevels(true);
        return jtaTM;
    }

    @Bean(name = "txAdvice")
    public TransactionInterceptor getAdvisor(@Qualifier("springTransactionManager") JtaTransactionManager txManager)
            throws Exception {
        TransactionInterceptor tsi = new TransactionInterceptor();
        Properties properties = new Properties();
        properties.setProperty("get*", "PROPAGATION_SUPPORTS");
        properties.setProperty("select*", "PROPAGATION_SUPPORTS");
        properties.setProperty("load*", "PROPAGATION_SUPPORTS");
        properties.setProperty("query*", "PROPAGATION_SUPPORTS");
        properties.setProperty("list*", "PROPAGATION_SUPPORTS");
        properties.setProperty("add*", "PROPAGATION_REQUIRED");
        properties.setProperty("insert*", "PROPAGATION_REQUIRED");
        properties.setProperty("save*", "PROPAGATION_REQUIRED");
        properties.setProperty("update*", "PROPAGATION_REQUIRED");
        properties.setProperty("modify*", "PROPAGATION_REQUIRED");
        properties.setProperty("do*", "PROPAGATION_REQUIRED");
        properties.setProperty("del*", "PROPAGATION_REQUIRED");
        properties.setProperty("remove*", "PROPAGATION_REQUIRED");
        properties.setProperty("process*", "PROPAGATION_REQUIRED");
        properties.setProperty("create*", "PROPAGATION_REQUIRED");
        properties.setProperty("valid*", "PROPAGATION_REQUIRED");
        properties.setProperty("do*", "PROPAGATION_REQUIRED");
        properties.setProperty("write*", "PROPAGATION_REQUIRED");
        properties.setProperty("cancel*", "PROPAGATION_REQUIRED");
        properties.setProperty("*", "readOnly");
        tsi.setTransactionAttributes(properties);
        tsi.setTransactionManager(txManager);
        return tsi;
    }

    @Bean
    public BeanNameAutoProxyCreator txProxy() {
        BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator();
        creator.setInterceptorNames("txAdvice");
        creator.setBeanNames("*ServiceImpl");
        creator.setProxyTargetClass(true);
        return creator;
    }
}

8 mapper层根据上面映射建立三个,不同的文件夹处理不同的数据库

9. servicec层

此处的每个方法都是支持事物的,在前面AutoProxyRegist类已经配置,以insert开头的方法支持事物的

至此完工!

发布了56 篇原创文章 · 获赞 86 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/qq_32331997/article/details/85286786
今日推荐