背景

我们平时在用springboot开发时,要使用事务,只需要在方法上添加@Transaction注解即可,但这种方式只适用单数据源,在多数据源下就不再适用;

比如在多数据源下,我们在一个方法里执行了数据源A的操作,又执行了数据源B的操作,如果报错了,事务只会回滚主数据源或者是指定事务的数据源数据(@Transactional(value="指定事务")),另一个数据源是不会回滚的;

这种情况下,单纯的@Transactional事务注解是无法实现的,此时就需要用到多数据源事务管理;

以下项目里实现了普通情况下的事务处理和使用springboot-jta-atomikos事务处理

本文主要介绍使用springboot-jta-atomikos来实现;

项目目录结构

实现

1.添加依赖 pom.xml

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

2.配置数据库连接信息 application.properties

#atomikos测试
spring.datasource.test1.url=jdbc:mysql://127.0.0.1:3306/test1?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai
spring.datasource.test1.user=root
spring.datasource.test1.password=arsenal spring.datasource.test2.url=jdbc:mysql://127.0.0.1:3306/test2?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai
spring.datasource.test2.user=root
spring.datasource.test2.password=arsenal

3.创建多数据源 DBAtomikosConfig.java

package com.llq.atomikos.config;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.jta.JtaTransactionManager; import javax.sql.DataSource;
import javax.transaction.UserTransaction;
import java.util.Properties; /**
* @author lvlianqi
* @description
* @date 2022/3/7
*/
@Configuration
public class DBAtomikosConfig { //--------------------数据源1--------------------
@ConfigurationProperties(prefix = "spring.datasource.test1")
@Bean
public Properties testOneProperties() {
return new Properties();
} @Bean(name = "testOneDataSource")
@Primary
public DataSource testOneDataSource() {
AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
Properties prop = testOneProperties();
ds.setXaDataSourceClassName("com.mysql.cj.jdbc.MysqlXADataSource");
ds.setUniqueResourceName("testOne");
ds.setXaProperties(prop);
return ds;
} @Bean
@Primary
public JdbcTemplate testOneJdbcTemplate(@Qualifier("testOneDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
} //--------------------数据源2--------------------
@ConfigurationProperties(prefix = "spring.datasource.test2")
@Bean
public Properties testTwoProperties() {
return new Properties();
} @Bean(name = "testTwoDataSource")
public DataSource testTwoDataSource() {
AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
Properties prop = testTwoProperties();
ds.setXaDataSourceClassName("com.mysql.cj.jdbc.MysqlXADataSource");
ds.setUniqueResourceName("testTwo");
ds.setXaProperties(prop);
return ds;
} @Bean
public JdbcTemplate testTwoJdbcTemplate(@Qualifier("testTwoDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
//--------------------配置spring的JtaTransactionManager,底层委派给atomikos进行处理--------------------
@Bean
public JtaTransactionManager jtaTransactionManager () {
UserTransactionManager userTransactionManager = new UserTransactionManager();
UserTransaction userTransaction = new UserTransactionImp();
return new JtaTransactionManager(userTransaction, userTransactionManager);
}
}

4.测试事务类 TestAtomikos.java

package com.llq.atomikos.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; /**
* @author lvlianqi
* @description
* @date 2022/3/7
*/
@Service
public class TestAtomikos implements ITest{ @Qualifier("testOneJdbcTemplate")
@Autowired
private JdbcTemplate testOneJdbcTemplate; @Qualifier("testTwoJdbcTemplate")
@Autowired
private JdbcTemplate testTwoJdbcTemplate; /**
* 测试正常情况
*/
@Transactional(rollbackFor = Exception.class, value = "jtaTransactionManager")
public void test() {
testOneJdbcTemplate.execute("insert into user (name, age) values ('张三', 18);");
testTwoJdbcTemplate.execute("insert into user (name, age) values ('李四', 20);");
} /**
* 测试异常情况
*/
@Transactional(rollbackFor = Exception.class, value = "jtaTransactionManager")
public void testByException() {
testOneJdbcTemplate.execute("insert into user (name, age) values ('张三', 18);");
testTwoJdbcTemplate.execute("insert into user (name, age) values ('李四', 20);");
int i = 1/0;
}
}

5.测试 SpringbootAtomikosApplicationTests.java

    //使用atomikos
private static Class CLS = TestAtomikos.class; @Autowired
ApplicationContext applicationContext; @Test
public void testByException() {
ITest test = (ITest) applicationContext.getBean(CLS);
test.testByException();
}

测试结果

执行错误



数据库test1 user表没有记录



数据库test2 user表没有记录

springboot-jta-atomikos多数据源事务管理的更多相关文章

  1. spring+springmvc+mybatis+oracle+atomikos+jta实现多数据源事务管理

    ---恢复内容开始---   在做项目过程中,遇到了需要一个项目中访问两个数据库的情况,发现使用常规的spring管理事务,导致事务不能正常回滚,因此,采用了jta+atomikos的分布式数据源方式 ...

  2. spring boot 或 spring 集成 atomikos jta 完成多数据源事务管理

    前言:对于事务,spring 不提供自己的实现,只是定义了一个接口来供其他厂商实现,具体些的请看我的这篇文章: https://www.cnblogs.com/qiaoyutao/p/11289996 ...

  3. Spring+JTA+Atomikos+mybatis分布式事务管理

    我们平时的工作中用到的Spring事务管理是管理一个数据源的.但是如果对多个数据源进行事务管理该怎么办呢?我们可以用JTA和Atomikos结合Spring来实现一个分布式事务管理的功能.了解JTA可 ...

  4. SpringBoot2 整合JTA组件,多数据源事务管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.JTA组件简介 1.JTA基本概念 JTA即Java-Transaction-API,JTA允许应用程序执行分布式事务处理,即在两个或多个 ...

  5. springbootdruidmybatismysql多数据源事务管理

    springboot+druid+mybatis+mysql+多数据源事务管理 分布式事务在java中的解决方案就是JTA(即Java Transaction API):springboot官方提供了 ...

  6. 事务隔离级别与传播机制,spring+mybatis+atomikos实现分布式事务管理

    1.事务的定义:事务是指多个操作单元组成的合集,多个单元操作是整体不可分割的,要么都操作不成功,要么都成功.其必须遵循四个原则(ACID). 原子性(Atomicity):即事务是不可分割的最小工作单 ...

  7. Spring事务隔离级别与传播机制详解,spring+mybatis+atomikos实现分布式事务管理

    原创说明:本文为本人原创作品,绝非他处转载,转账请注明出处 1.事务的定义:事务是指多个操作单元组成的合集,多个单元操作是整体不可分割的,要么都操作不成功,要么都成功.其必须遵循四个原则(ACID). ...

  8. spring JTA多数据源事务管理详细教程

    <context:annotation-config /> <!-- 使用注解的包路径 --> <context:component-scan base-package= ...

  9. 传统Spring配置JTA 实现多数据源事务的统一管理

    分布式事务是指事务的参与者.支持事务的服务器.资源管理器以及事务管理器分别位于分布系统的不同节点之上,在两个或多个网络计算机资源上访问并且更新数据,将两个或多个网络计算机的数据进行的多次操作作为一个整 ...

随机推荐

  1. C++ 类对象内存模型分析

    编译环境:Windows10 + VS2015 1.空类占用的内存空间 类占内存空间是只类实例化后占用内存空间的大小,类本身是不会占内存空间的.用sizeof计算类的大小时,实际上是计算该类实例化后对 ...

  2. 010 Linux 文本统计与去重 (wc 和 uniq)

    wc 命令一般是作为组合命令的一员与其他命令一同起到统计的作用.而一般情况下使用wc -l 命令较多. uniq 可检查文本文件中重复出现的行,一般与 sort 命令结合使用.一起组合搭配使用完成统计 ...

  3. js 斐波那契数列的获取和曲线的实现(每日一更)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  4. [学习笔记]Linux环境下部署 .Net5 程序

    ​公司的项目需要部署到一台公网的linux服务器,以便同事们测试小程序. 目标服务器是新搭建的CentOS 8虚拟机,以非docker的方式部署.现记录过程便于日后部署至项目甲方的服务器上,因为甲方的 ...

  5. Firewalld工作区

    firewalld的字符界面管理工具是 firewall-cmd  firewalld默认配置文件有两个:/usr/lib/firewalld/ (系统配置,尽量不要修改)和 /etc/firewal ...

  6. Java 中的锁原理、锁优化、CAS、AQS 详解!(转)

    1.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 2.锁实现的基本原理 2.1.volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新, ...

  7. DNS解析域名过程

    DNS解析域名过程 使用域名转换成IP地址,先读取本地HOST文件,本地文件没有从当前电信网管获取对应IP. 本地host文件 C:\Windows\System32\drivers\etc 画图演示 ...

  8. kubectl详解

    kubectl详解 目录 kubectl详解 一.陈述式管理 1. 陈述式资源管理方法 2. k8s相关信息查看 2.1 查看版本信息 2.2 查看资源对象简写 2.3 查看集群信息 2.4 配置ku ...

  9. 用Java实现生成图片验证码

    通过代码实现生成一个随机验证码图片,且生成后自动打开: package day_12_17; import javax.imageio.ImageIO; import java.awt.*; impo ...

  10. Spring Boot AOP 扫盲,实现接口访问的统一日志记录

    AOP 是 Spring 体系中非常重要的两个概念之一(另外一个是 IoC),今天这篇文章就来带大家通过实战的方式,在编程猫 SpringBoot 项目中使用 AOP 技术为 controller 层 ...