• SpringBoot多数据源与Atomikos分布式事务【SpringBoot+JTA+Atomikos】


    1:pom.xml引入相关依赖jar

    <!--springboot整合mybatis的依赖 -->
            <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.4</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.22</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jta-atomikos -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jta-atomikos</artifactId>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.16</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>

    2、application.yml配置多数据源

    spring:
      datasource:
        test1:
          url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT&allowMultiQueries=true
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
          sql-script-encoding: UTF-8
          type: com.zaxxer.hikari.HikariDataSource
          initialization-mode: always
          continue-on-error: true
          hikari:
            minimum-idle: 5
            connection-test-query: SELECT 1 FROM DUAL
            maximum-pool-size: 20
            auto-commit: true
            idle-timeout: 30000
            pool-name: SpringBootDemoHikariCP
            max-lifetime: 60000
            connection-timeout: 30000
          logging:
            level:
              com.qjc.dao.Test1: TARCE
          borrowConnectionTimeout: 30
          loginTimeout: 30
          maintenanceInterval: 60
          maxIdleTime: 60
          maxLifetime: 20000
          maxPoolSize: 25
          minPoolSize: 3
          uniqueResourceName: test1
          testQuery: SELECT 1 FROM DUAL
        test2:
          url: jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT&allowMultiQueries=true
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
          sql-script-encoding: UTF-8
          type: com.zaxxer.hikari.HikariDataSource
          initialization-mode: always
          continue-on-error: true
          hikari:
            minimum-idle: 5
            connection-test-query: SELECT 1 FROM DUAL
            maximum-pool-size: 20
            auto-commit: true
            idle-timeout: 30000
            pool-name: SpringBootDemoHikariCP
            max-lifetime: 60000
            connection-timeout: 30000
          logging:
            level:
             com.qjc.dao.Test2: TARCE
          borrowConnectionTimeout: 30
          loginTimeout: 30
          maintenanceInterval: 60
          maxIdleTime: 60
          maxLifetime: 20000
          maxPoolSize: 25
          minPoolSize: 3
          uniqueResourceName: test2
          testQuery: SELECT 1 FROM DUAL

    3、具体数据源的config和application.yml配置的数据源对应

    package com.example.config;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    import lombok.Data;
    
    @Data
    @ConfigurationProperties(prefix = "spring.datasource.test1")
    public class DBConfig1 {
        private String url;
        private String userName;
        private String passWord;
        private int minPoolSize;
        private int maxPoolSize;
        private int maxLifetime;
        private int borrowConnectionTimeout;
        private int loginTimeout;
        private int maintenanceInterval;
        private int maxIdleTime;
        private String testQuery;
        private String uniqueResourceName;
    }
    package com.example.config;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    import lombok.Data;
    
    @Data
    @ConfigurationProperties(prefix = "spring.datasource.test2")
    public class DBConfig2 {
        private String url;
        private String userName;
        private String passWord;
        private int minPoolSize;
        private int maxPoolSize;
        private int maxLifetime;
        private int borrowConnectionTimeout;
        private int loginTimeout;
        private int maintenanceInterval;
        private int maxIdleTime;
        private String testQuery;
        private String uniqueResourceName;
    }

    4、启动类上加具体数据源的config

    package com.example;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    
    import com.example.config.DBConfig1;
    import com.example.config.DBConfig2;
    
    @SpringBootApplication
    @EnableConfigurationProperties({DBConfig1.class, DBConfig2.class})
    public class App {
    
        public static void main(String[] args) {
            SpringApplication.run(App.class, args);
        }
    }

    5、配置数据源加事务配置

    package com.example.config;
    
    import java.sql.SQLException;
    
    import javax.sql.DataSource;
    
    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.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    
    import com.atomikos.jdbc.AtomikosDataSourceBean;
    import com.mysql.cj.jdbc.MysqlXADataSource;
    
    @Configuration
    //basePackages 最好分开配置,放在同一个文件夹可能会报错
    @MapperScan(basePackages = {"com.example.mapper.test1"},sqlSessionTemplateRef = "test1SqlSessionTemplate")
    public class DataSourceConfig1 {
        /**
         * 配置数据源
         * @return
         */
        @Primary
        @Bean("test1DataSource")
        public DataSource e3shopDataSource(DBConfig1 eBConfig1) throws SQLException {
            //创建xa datasource
            MysqlXADataSource mysqlXADataSource=new MysqlXADataSource();
            mysqlXADataSource.setUrl(eBConfig1.getUrl());
            mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
            mysqlXADataSource.setPassword(eBConfig1.getPassWord());
            mysqlXADataSource.setUser(eBConfig1.getUserName());
            mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
    
            //2.注册到我们全局事务上
            AtomikosDataSourceBean xaDataSource =new AtomikosDataSourceBean();
            xaDataSource.setXaDataSource(mysqlXADataSource);
            xaDataSource.setUniqueResourceName(eBConfig1.getUniqueResourceName());
            xaDataSource.setMinPoolSize(eBConfig1.getMinPoolSize());
            xaDataSource.setMaxPoolSize(eBConfig1.getMaxPoolSize());
            xaDataSource.setBorrowConnectionTimeout(eBConfig1.getBorrowConnectionTimeout());
            xaDataSource.setLoginTimeout(eBConfig1.getLoginTimeout());
            xaDataSource.setMaintenanceInterval(eBConfig1.getMaintenanceInterval());
            xaDataSource.setMaxIdleTime(eBConfig1.getMaxIdleTime());
            xaDataSource.setTestQuery(eBConfig1.getTestQuery());
            return xaDataSource;
    
        }
        /**
         * sqlSessionFactory
         * @param dataSource
         * @return
         * @throws Exception
         */
        @Primary
        @Bean("test1SqlSessionFactory")
        public SqlSessionFactory e3shopSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSource);
            return sqlSessionFactoryBean.getObject();
        }
    
        /**
         * sqlsessionTemplate
         * @param sqlSessionFactory
         * @return
         */
        @Primary
        @Bean(name = "test1SqlSessionTemplate")
        public SqlSessionTemplate e3shopSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
            return new SqlSessionTemplate(sqlSessionFactory);
        }
    }
    package com.example.config;
    
    import java.sql.SQLException;
    
    import javax.sql.DataSource;
    
    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.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import com.atomikos.jdbc.AtomikosDataSourceBean;
    import com.mysql.cj.jdbc.MysqlXADataSource;
    
    @Configuration
    //basePackages 最好分开配置,放在同一个文件夹可能会报错
    @MapperScan(basePackages = {"com.example.mapper.test2"},sqlSessionTemplateRef = "test2SqlSessionTemplate")
    public class DataSourceConfig2 {
        /**
         * 配置数据源
         * @return
         */
        @Bean("test2DataSource")
        public DataSource e3shopDataSource(DBConfig2 eBConfig1) throws SQLException {
            //创建xa datasource
            MysqlXADataSource mysqlXADataSource=new MysqlXADataSource();
            mysqlXADataSource.setUrl(eBConfig1.getUrl());
            mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
            mysqlXADataSource.setPassword(eBConfig1.getPassWord());
            mysqlXADataSource.setUser(eBConfig1.getUserName());
            mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
    
            //2.注册到我们全局事务上
            AtomikosDataSourceBean xaDataSource =new AtomikosDataSourceBean();
            xaDataSource.setXaDataSource(mysqlXADataSource);
            xaDataSource.setUniqueResourceName(eBConfig1.getUniqueResourceName());
            xaDataSource.setMinPoolSize(eBConfig1.getMinPoolSize());
            xaDataSource.setMaxPoolSize(eBConfig1.getMaxPoolSize());
            xaDataSource.setBorrowConnectionTimeout(eBConfig1.getBorrowConnectionTimeout());
            xaDataSource.setLoginTimeout(eBConfig1.getLoginTimeout());
            xaDataSource.setMaintenanceInterval(eBConfig1.getMaintenanceInterval());
            xaDataSource.setMaxIdleTime(eBConfig1.getMaxIdleTime());
            xaDataSource.setTestQuery(eBConfig1.getTestQuery());
            return xaDataSource;
    
        }
        /**
         * sqlSessionFactory
         * @param dataSource
         * @return
         * @throws Exception
         */
        @Bean("test2SqlSessionFactory")
        public SqlSessionFactory e3shopSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSource);
            return sqlSessionFactoryBean.getObject();
        }
    
        /**
         * sqlsessionTemplate
         * @param sqlSessionFactory
         * @return
         */
        @Bean(name = "test2SqlSessionTemplate")
        public SqlSessionTemplate e3shopSqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
            return new SqlSessionTemplate(sqlSessionFactory);
        }
    }

    6、添加mapper层操作数据库

    package com.example.mapper.test1;
    
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Param;
    
    @Mapper
    public interface User1Mapper {
        @Insert("INSERT INTO user (username, sex, password) VALUES ( #{username}, #{sex}, #{password})")
        int insertUser(@Param("username")String username,@Param("sex")String  sex,@Param("password")String password);
    }
    package com.example.mapper.test2;
    
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Param;
    
    @Mapper
    public interface User2Mapper {
        @Insert("INSERT INTO user (username, sex, password) VALUES ( #{username}, #{sex}, #{password})")
        int insertUser(@Param("username")String username,@Param("sex")String  sex,@Param("password")String password);
    }

    7、service层添加事务@Transactional

    package com.example.service.impl;
    
    import javax.transaction.Transactional;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.example.mapper.test1.User1Mapper;
    import com.example.mapper.test2.User2Mapper;
    import com.example.service.UserService;
    @Service
    public class UserServiceImpl implements UserService {
        
        @Autowired
        private User1Mapper user1Mapper;
        @Autowired
        private User2Mapper user2Mapper;
        @Transactional
        @Override
        public int addUser(String username, String sex, String password) {
            int rtu1=user1Mapper.insertUser(username, sex, password);
            int rtu2=user2Mapper.insertUser(username, sex, password);
            return rtu1+rtu2;
        }
    
    }

    完成,剩余的就是Controller层调用了

  • 相关阅读:
    python--将jenkins配置的任务导出到Excel
    python--终端工具之subprocess
    jquery-触底加载无限滚动
    python-比较字典value的最大值
    Linux-查看cpu核数和个数、查看内存的命令
    python读取本地正在运行的docker容器
    关于get 和post 方法的比较
    git相关的一篇不错的文章
    Java 函数调用是传值还是传引用? 从字节码角度来看看!
    Unity3D移动平台动态读取外部文件全解析
  • 原文地址:https://www.cnblogs.com/h-z-y/p/14255464.html
Copyright © 2020-2023  润新知