zoukankan      html  css  js  c++  java
  • 基于boot实现的单例多库分布式事务

    场景描述:

           业务系统中存在针对用户对一些特定字段(如:身份证、银行卡号)的操作,需要进行日志记录及入库日志。项目架构是基于boot为基石的SpringCloud分布式架构,业务模块暂时称呼为模块A,日志记录属于公共模块暂时称呼为模块B。模块A操作步骤成功之后,会调用模块B进行日志记录。

    名词解释:

           数据库事务的ACID (原子性、一致性、隔离性、持久性),分布式事务的BASE理论(分布式事务要求实现最终一致性)。

    实现核心技术:

           Jta+atomikos

      jta:java中对事务处理的api

      atomikos:为Java平台提供增值服务的并且开源类事务管理器

    实现步骤:

    1、在pom文件文件中添加依赖

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

    2、在application.properties中配置两个数据源的

    spring:
      datasource:
        # 数据库1
        db1:
          driver-class-name: com.mysql.cj.jdbc.Driver
          type: com.alibaba.druid.pool.DruidDataSource
          jdbc-url: jdbc:mysql://localhost:3306/test1?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&allowMultiQueries=true
          username: root
          password: newpwd
    
        # 数据库2
        db2:
          driver-class-name: com.mysql.cj.jdbc.Driver
          type: com.alibaba.druid.pool.DruidDataSource
          jdbc-url: jdbc:mysql://localhost:3306/test2?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&allowMultiQueries=true
          username: root
          password: newpwd
    
      # 分布式锁
      jta:
        # log-dir: classpath*:tx-logs
        transaction-manager-id: txManager

    3、添加conf配置类:

    @Data
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    public class DB1Config {
    
        @Value("${spring.datasource.db1.jdbc-url}")
        private String url_jdbc;
    
        @Value("${spring.datasource.db1.username}")
        private String username;
    
        @Value("${spring.datasource.db1.password}")
        private String password;
    }

    4、添加数据源类:

    @Configuration
    @MapperScan(basePackages = "com.example.mapper.db1", sqlSessionFactoryRef = "db1SqlSessionFactory")
    public class DB1DataSourcesConfig {
    
        @Primary
        @Bean(name = "db1DataSource")
        public DataSource dataSource(DB1Config DB1Config) {
            MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
            mysqlXADataSource.setUrl(DB1Config.getUrl_jdbc());
            mysqlXADataSource.setUser(DB1Config.getUsername());
            mysqlXADataSource.setPassword(DB1Config.getPassword());
            mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
    
            AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
            atomikosDataSourceBean.setXaDataSource(mysqlXADataSource);
            atomikosDataSourceBean.setUniqueResourceName("db1DataSource");
    
            return atomikosDataSourceBean;
        }
    
        @Primary
        @Bean(name = "db1SqlSessionFactory")
        public SqlSessionFactory sqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
            SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
            sessionFactoryBean.setDataSource(dataSource);
            sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/db1/*.xml"));
    
            org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
            configuration.setMapUnderscoreToCamelCase(true);
    
            sessionFactoryBean.setConfiguration(configuration);
            return sessionFactoryBean.getObject();
        }
    
        @Primary
        @Bean(name = "db1SqlSessionTemplate")
        public SqlSessionTemplate sqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
            return new SqlSessionTemplate(sqlSessionFactory);
        }
    }

    5、添加db2的配置类和数据源类,差别与db1的地方在于:db1是默认的数据源,有@Primary注解,db2的不需要。

    6、在启动类上添加注解,指定扫描路径:

    @EnableConfigurationProperties(value = {DB2Config.class, DB1Config.class})

    7、在要进行事务控制的方法上添加@Transaction注解,通过调用dao层的方法,实现对数据库的操作。(此处可以用jpa或者mybatis)

    总结:

      SpringBoot 通过在启动时加载不同的数据源,并将不同的数据源注入到不同的 repository 包下,从而实现项目多数据源操作,在项目中使用多数据源时,需要用到哪个数据源,只需要将对应包下的 repository 注入操作即可。

  • 相关阅读:
    Jpa 一对多级联查询 排序设置
    Spring Data Jpa Specification 调用Oracle 函数/方法
    Spring boot 集成 阿里 Mqtt
    将Jquery序列化后的表单值转换成Json
    Linux安装和卸载MySQL5.7
    NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{3bFuKD5MTOWOCfJ1ZFrfdw}{192.168.0.105}{192.168.0.105:9301}]]
    Docker下安装RabbitMQ
    JAVA数据结构与算法-稀疏数组
    第一篇博客
    测试用例编写方法:边界值分析方法
  • 原文地址:https://www.cnblogs.com/cecWork/p/12098060.html
Copyright © 2011-2022 走看看