一、前言

       springboot整合多数据源解决分布式事务。

            1.多数据源采用分包策略 

            2.全局分布式事务管理:jta-atomikos。

       在此记录下,分享给大家。

二、springboot整合多数据源解决分布式事务

1、pom文件 依赖引入

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.1.8.RELEASE</version>

<relativePath />

</parent>

<dependencies>

<!-- SpringBoot 测试 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

<!-- SpringBoot web组件 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<!-- mybatis 支持 SpringBoot -->

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>1.1.1</version>

</dependency>

<!-- mysql 驱动 -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.38</version>

</dependency>

<!-- 全局事务集中管理解决分布式事务 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jta-atomikos</artifactId>

</dependency>

<!-- SpringBoot 自动配置 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-configuration-processor</artifactId>

<optional>true</optional>

</dependency>

<!-- 注解式插入/构建/优雅代码 -->

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

<version>1.18.4</version>

</dependency>

</dependencies>

2 application.yml 新增配置

spring:

datasource:

## 用户数据库

user:

url: jdbc:mysql://127.0.0.1:3306/yys_user

username: root

password: 123456

borrowConnectionTimeout: 30

loginTimeout: 30

maintenanceInterval: 60

maxIdleTime: 60

maxLifetime: 20000

maxPoolSize: 25

minPoolSize: 3

uniqueResourceName:
userDataSource

testQuery: select 1

## 订单数据库

order:

url: jdbc:mysql://127.0.0.1:3306/yys_order

username: root

password: 123456

borrowConnectionTimeout: 30

loginTimeout: 30

maintenanceInterval: 60

maxIdleTime: 60

maxLifeTime: 20000

maxPoolSize: 25

minPoolSize: 3

uniqueResourceName:
orderDataSource

testQuery: select 1

3userConfig.java

@ConfigurationProperties(prefix = "spring.datasource.user")

@Data

public class UserConfig {

private String url;

private String userName;

private String password;

private int
minPoolSize;

private int
maxPoolSize;

private int
maxLifeTime;

private int
maxIdleTime;

private int
loginTimeout;

private int
maintenanceInterval;

private int borrowConnectionTimeout;

private String testQuery;

private String
uniqueResourceName;

}

4userDataSourceConfig.java

/**

 * 用户数据源

 *      Config

 * @author yys

 */

@Configuration

@MapperScan(basePackages = "com.yys.user.mapper", sqlSessionTemplateRef
= "userSqlSessionTemplate")

public class UserDataSourceConfig {

/**

     * 创建 XADataSource

     * @return

     */

@Bean("userDataSource")

public DataSource userDataSource(UserConfig
userConfig) throws SQLException {

// 1、创建Mysql XADataSource

MysqlXADataSource
mysqlXaDataSource = new MysqlXADataSource();

mysqlXaDataSource.setUrl(userConfig.getUrl());

mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);

mysqlXaDataSource.setPassword(userConfig.getPassword());

mysqlXaDataSource.setUser(userConfig.getUserName());

mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);

// 2、将本地事务注册到 Atomikos 全局事务

AtomikosDataSourceBean
xaDataSource = new AtomikosDataSourceBean();

xaDataSource.setXaDataSource(mysqlXaDataSource);

xaDataSource.setUniqueResourceName(userConfig.getUniqueResourceName());

xaDataSource.setMinPoolSize(userConfig.getMinPoolSize());

xaDataSource.setMaxPoolSize(userConfig.getMaxPoolSize());

xaDataSource.setMaxLifetime(userConfig.getMaxLifeTime());

xaDataSource.setBorrowConnectionTimeout(userConfig.getBorrowConnectionTimeout());

xaDataSource.setLoginTimeout(userConfig.getLoginTimeout());

xaDataSource.setMaintenanceInterval(userConfig.getMaintenanceInterval());

xaDataSource.setMaxIdleTime(userConfig.getMaxIdleTime());

xaDataSource.setTestQuery(userConfig.getTestQuery());

return xaDataSource;

}

/**

     * 创建 SQL会话工厂

     * @param dataSource

     * @return

     * @throws Exception

     */

@Bean("userSqlSessionFactory")

public SqlSessionFactory userSqlSessionFactory(@Qualifier("userDataSource") DataSource
dataSource) throws Exception {

SqlSessionFactoryBean
sqlSessionFactoryBean = new SqlSessionFactoryBean();

sqlSessionFactoryBean.setDataSource(dataSource);

return
sqlSessionFactoryBean.getObject();

}

/**

     * 创建用户 SqlSession模板

     * @param sqlSessionFactory

     * @return

     */

@Bean("userSqlSessionTemplate")

public SqlSessionTemplate
userSqlSessionTemplate(@Qualifier("userSqlSessionFactory")
SqlSessionFactory sqlSessionFactory) {

return new
SqlSessionTemplate(sqlSessionFactory);

}

}

5orderConfig.java

@ConfigurationProperties(prefix = "spring.datasource.order")

@Data

public class OrderConfig {

private String url;

private String userName;

private String password;

private int minPoolSize;

private int
maxPoolSize;

private int
maxLifeTime;

private int
maxIdleTime;

private int
loginTimeout;

private int
maintenanceInterval;

private int
borrowConnectionTimeout;

private String testQuery;

private String
uniqueResourceName;

}

6orderDataSourceConfig.java

/**

 * 订单数据源

 *      Config

 * @author yys

 */

@Configuration

@MapperScan(basePackages = "com.yys.order.mapper",
sqlSessionTemplateRef = "orderSqlSessionTemplate")

public class OrderDataSourceConfig {

/**

     * 创建 XADataSource

     * @return

     */

@Bean("orderDataSource")

public DataSource orderDataSource(OrderConfig
orderConfig) throws SQLException {

// 1、创建Mysql XADataSource

MysqlXADataSource
mysqlXaDataSource = new MysqlXADataSource();

mysqlXaDataSource.setUrl(orderConfig.getUrl());

mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);

mysqlXaDataSource.setPassword(orderConfig.getPassword());

mysqlXaDataSource.setUser(orderConfig.getUserName());

mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);

// 2、将本地事务注册到 Atomikos 全局事务

AtomikosDataSourceBean xaDataSource
= new AtomikosDataSourceBean();

xaDataSource.setXaDataSource(mysqlXaDataSource);

xaDataSource.setUniqueResourceName(orderConfig.getUniqueResourceName());

xaDataSource.setMinPoolSize(orderConfig.getMinPoolSize());

xaDataSource.setMaxPoolSize(orderConfig.getMaxPoolSize());

xaDataSource.setMaxLifetime(orderConfig.getMaxLifeTime());

xaDataSource.setBorrowConnectionTimeout(orderConfig.getBorrowConnectionTimeout());

xaDataSource.setLoginTimeout(orderConfig.getLoginTimeout());

xaDataSource.setMaintenanceInterval(orderConfig.getMaintenanceInterval());

xaDataSource.setMaxIdleTime(orderConfig.getMaxIdleTime());

xaDataSource.setTestQuery(orderConfig.getTestQuery());

return xaDataSource;

}

/**

     * 创建 SQL会话工厂

     * @param dataSource

     * @return

     * @throws Exception

     */

@Bean("orderSqlSessionFactory")

public SqlSessionFactory orderSqlSessionFactory(@Qualifier("orderDataSource") DataSource
dataSource) throws Exception {

SqlSessionFactoryBean
sqlSessionFactoryBean = new SqlSessionFactoryBean();

sqlSessionFactoryBean.setDataSource(dataSource);

return sqlSessionFactoryBean.getObject();

}

/**

     * 创建订单 SqlSession模板

     * @param
sqlSessionFactory

     * @return

     */

@Bean("orderSqlSessionTemplate")

public SqlSessionTemplate
orderSqlSessionTemplate(@Qualifier("orderSqlSessionFactory")
SqlSessionFactory sqlSessionFactory) {

return new
SqlSessionTemplate(sqlSessionFactory);

}

}

UserService.java

public class UserService {

@Autowired

private UserMapper
userMapper;

@Autowired

private OrderMapper
orderMapper;

// 全局事务处理器

// 事务底层原理采用aop技术做增强

// 无需再指定某个事务管理器,全交给 Atomikos 全局事务

@Transactional

public Boolean addUser(String name,
Integer age, Double amount, String address) {

// 操作用户库

int i =
userMapper.addUser(name, age);

// 操作订单库

int j =
orderMapper.addOrder(amount, address);

// 测试事务回滚(age = 0:回滚;age > 0:事务提交)

int flag = 1 / age;

return i > 0 && j
> 0;

}

}

springboot整合多数据源解决分布式事务

springboot整合多数据源解决分布式事务的更多相关文章

  1. RabbitMQ解决分布式事务

    案例:经典案例,以目前流行点外卖的案例,用户下单后,调用订单服务,让后订单服务调用派单系统通知送外卖人员送单,这时候订单系统与派单系统采用MQ异步通讯. RabbitMQ解决分布式事务原理: 采用最终 ...

  2. 3分钟搞定SpringBoot+Mybatis+druid多数据源和分布式事务

    文章来自: https://blog.csdn.net/qq_29242877/article/details/79033287 在一些复杂的应用开发中,一个应用可能会涉及到连接多个数据源,所谓多数据 ...

  3. 【分布式事务】使用atomikos+jta解决分布式事务问题

    一.前言 分布式事务,这个问题困惑了小编很久,在3个月之前,就间断性的研究分布式事务.从MQ方面,数据库事务方面,jta方面.近期终于成功了,使用JTA解决了分布式事务问题.先写一下心得,后面的二级提 ...

  4. LCN解决分布式事务原理解析+项目实战(原创精华版)

    写在前面: 原创不易,如果觉得不错推荐一下,谢谢! 由于工作需要,公司的微服务项目需解决分布式事务的问题,且由我进行分布式事务框架搭建和整合工作. 那么借此机会好好的将解决分布式事务的内容进行整理一下 ...

  5. 使用kafka消息队列解决分布式事务(可靠消息最终一致性方案-本地消息服务)

    微服务框架Spring Cloud介绍 Part1: 使用事件和消息队列实现分布式事务 本文转自:http://skaka.me/blog/2016/04/21/springcloud1/ 不同于单一 ...

  6. SpringBoot整合Mybatis,并实现事务控制

    SpringBoot整合Mybatis,并实现事务控制 1. 在pom文件里添加相关maven文件 <parent> <groupId>org.springframework. ...

  7. 二、springboot项目使用seata实现分布式事务

    所有文章 https://www.cnblogs.com/lay2017/p/12078232.html 正文 在上一篇文章中,我们简单地了解了一下什么是seata.它是来自阿里巴巴的内部项目不断地发 ...

  8. springBoot整合多数据源

    springBoot整合相关 1:springBoot整合多数据源: 应用场景:     项目需要同时连接两个不同的数据库A, B,并且它们都为主从架构,一台写库,多台读库. 工具/版本: jdk1. ...

  9. 搞懂分布式技术19:使用RocketMQ事务消息解决分布式事务

    搞懂分布式技术19:使用RocketMQ事务消息解决分布式事务 初步认识RocketMQ的核心模块 rocketmq模块 rocketmq-broker:接受生产者发来的消息并存储(通过调用rocke ...

随机推荐

  1. Django基础-004 上下文管理器&中间件&前端公共代码复用

    一.上下文管理器 在views中重复使用的代码,可以在上下文管理器中实现 上下文管理器的处理流程如下: 1.先走完views里面的代码,将结果返回给前端 2.然后再将上下文的结果返回给前端 3.上下文 ...

  2. python 模拟点击微信

    from PyQt5 import QtCore,QtWidgets import win32gui, win32api, win32con # 调用win32api的模拟点击功能实现ctrl+v粘贴 ...

  3. 高校表白App-团队冲刺第五天

    今天要做什么 封装Adapter制作引导页 今天做了什么 成功封装工具类,为以后的轮播做了铺垫 遇到的问题 在封装时采用数组容器进行操作,只能添加图片作为元素,对于layout不可加入

  4. Appium - adb命令操作

    1.Android 调试桥adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信.它可为各种设备操作提供便利,如安装和调 ...

  5. React优化

    这里主要分析在函数式react中的优化,类组件有生命周期函数定义较明确 React的核心特征之一是单向数据流(props自上往下流) 这会导致一个问题:当父组件state更新后,其自身及其所有chil ...

  6. POJ1944

    poj1944 一道我不会做的贪心题. (思维才是OI的重点) 但是if您也不会,那就来听我瞎扯吧. 首先,这个图是一个圈,只能连接邻点,使所有求的点联通. 我们先不考虑环,那么就可以想出一个假的做法 ...

  7. String类型转成int类型

    在将String类型转换成int类型时: int n = Interger.parseInt(Stringnum); 如果报错,可以改成 int n = Interger.parseInt(Strin ...

  8. router-link与router-view的对应关系和映射特点

    router-link对应的router-view规律为: 1.根据to的值而定,值为一层(如 /child)则对应app.vue中的router-view: 值为两层,如 /second/child ...

  9. thinkphp 事物回滚

    1 $m=D('YourModel');//或者是M(); 2 $m2=D('YouModel2'); 3 $m->startTrans();//在第一个模型里启用就可以了,或者第二个也行 4 ...

  10. Verilog function的使用

    function的用法 function的标准写法如下: function  <返回值的类型或是范围>  (函数名): <端口说明语句> //input xxx <变量类 ...