当前位置: 首页 > news >正文

多数据源解决分布式事务

 环境:idea+springboot2.x

场景:调用addUser方法执行对两个数据库的表操作,如果方法出现异常就回滚

 

 

user数据库中的users表

 

order数据库中的order_number表

 

将各自的事务管理器改为统一事务管理器即可

第一步pom文件配置jta atomikos 依赖

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>2.2.2</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.10</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jta-atomikos</artifactId>
    </dependency>
  </dependencies>

第二步yml配置

spring:
  datasource:
    member:
      url: jdbc:mysql://localhost:3306/user?useSSL=false
      username: root
      password: root
      boorowConectionTimeout: 30
      loginTimeout: 30
      maintenanceInterval: 60
      maxIdleTime: 60
      maxLifetime: 20000
      maxPoolSize: 25
      minPoolSize: 3
      uniqueResourceName: orderDatasource
    order:
      url: jdbc:mysql://localhost:3306/order?useSSL=false
      username: root
      password: root
      borrowConnectionTimeout: 30
      loginTimeout: 30
      maintenanceInterval: 60
      maxIdleTime: 60
      maxLifetime: 20000
      maxPoolSize: 25
      minPoolSize: 3
      uniqueResourceName: memberDatasource

第三步配置编写MemberConfig和OrdeerConfig配置类

@Data
@ConfigurationProperties(prefix = "spring.datasource.member")
public class MemberConfig {
    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;
}
@Data
@ConfigurationProperties(prefix = "spring.datasource.order")
public class OrderConfig {
    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;
}

第五步将DataSource改为xaDataSource

以MemberDataSourceConfig为例,OrderDataSourceConfig操作步骤相同

/**
 * 创建DataSource 将我们的数据源统一交给我们的全局xa事务管理
 * @return
 */
@Bean(name = "memberDataSource")
public DataSource memberDataSource(MemberConfig memberConfig) throws SQLException {
    // 1.创建我们的xaDataSource
    MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
    mysqlXADataSource.setUrl(memberConfig.getUrl());
    mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
    mysqlXADataSource.setPassword(memberConfig.getPassWord());
    mysqlXADataSource.setUser(memberConfig.getUserName());
    mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
    // 2.注册到全局事务
    AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
    xaDataSource.setXaDataSource(mysqlXADataSource);
    xaDataSource.setUniqueResourceName(memberConfig.getUniqueResourceName());
    xaDataSource.setMinPoolSize(memberConfig.getMinPoolSize());
    xaDataSource.setMaxPoolSize(memberConfig.getMaxPoolSize());
    xaDataSource.setMaxLifetime(memberConfig.getMaxLifetime());
    xaDataSource.setBorrowConnectionTimeout(memberConfig.getBorrowConnectionTimeout());
    xaDataSource.setLoginTimeout(memberConfig.getLoginTimeout());
    xaDataSource.setMaintenanceInterval(memberConfig.getMaintenanceInterval());
    xaDataSource.setMaxIdleTime(memberConfig.getMaxIdleTime());
    xaDataSource.setTestQuery(memberConfig.getTestQuery());

//        return DataSourceBuilder.create().build(); // 原始的DataSource
    return xaDataSource; // 改为xaDataSource
}

第六步关闭事务管理器

 以MemberDataSourceConfig为例,OrderDataSourceConfig操作步骤相同

 

执行代码

 

 

 此时表中数据(已刷新)

 放行

 此时表中数据(已刷新)

 事务回滚

 

输入合法数据进行测试

 直接放行

数据已加入

 页面信息

 

相关文章:

  • 跳槽一次能涨多少?今天见识到跳槽天花板。
  • 【HTML期末学生大作业】 制作一个简单HTML宠物网页(HTML+CSS)
  • 分享一些冷门但却很实用的css样式
  • 写代码时记录的小技巧
  • Springboot 那年我双手插兜,手写一个excel导出
  • web自动化测试入门篇04——selenium+python基础方法封装
  • 21 【styled-components的使用】
  • Flink Checkpoint 问题排查实用指南
  • 0基础1天学会js-第二讲
  • 猿如意中的【PyCharm社区版】工具详情介绍
  • 【Docker】Docker安装Redis,并配置数据备份同步到宿主机
  • 图像的OTSU阈值化、双阈值化、半阈值化的原理及OpenCV代码实现
  • web前端期末大作业—— HTML+CSS豪华车 (9页)
  • 单片机扫盲
  • 面试八股-Java并发
  • __proto__ 和 prototype的关系
  • CentOS6 编译安装 redis-3.2.3
  • ES10 特性的完整指南
  • Flannel解读
  • Java-详解HashMap
  • leetcode98. Validate Binary Search Tree
  • oldjun 检测网站的经验
  • 从0实现一个tiny react(三)生命周期
  • 计算机在识别图像时“看到”了什么?
  • 数组大概知多少
  • scrapy中间件源码分析及常用中间件大全
  • 翻译 | The Principles of OOD 面向对象设计原则
  • 国内开源镜像站点
  • ​configparser --- 配置文件解析器​
  • # .NET Framework中使用命名管道进行进程间通信
  • #pragma once与条件编译
  • #QT(智能家居界面-界面切换)
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (C语言)fgets与fputs函数详解
  • (理论篇)httpmoudle和httphandler一览
  • (排序详解之 堆排序)
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (转)Google的Objective-C编码规范
  • (转)nsfocus-绿盟科技笔试题目
  • .Net 6.0 处理跨域的方式
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .Net FrameWork总结
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .Net8 Blazor 尝鲜
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • /etc/skel 目录作用
  • @Repository 注解
  • @Transactional 详解
  • [ vulhub漏洞复现篇 ] Celery <4.0 Redis未授权访问+Pickle反序列化利用
  • [ 蓝桥杯Web真题 ]-布局切换
  • [<事务专题>]
  • [20170705]diff比较执行结果的内容.txt
  • [Angular] 笔记 20:NgContent