背景

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

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

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

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

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

项目目录结构

实现

1.添加依赖 pom.xml

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

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

  1. #atomikos测试
  2. 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
  3. spring.datasource.test1.user=root
  4. spring.datasource.test1.password=arsenal
  5. 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
  6. spring.datasource.test2.user=root
  7. spring.datasource.test2.password=arsenal

3.创建多数据源 DBAtomikosConfig.java

  1. package com.llq.atomikos.config;
  2. import com.atomikos.icatch.jta.UserTransactionImp;
  3. import com.atomikos.icatch.jta.UserTransactionManager;
  4. import org.springframework.beans.factory.annotation.Qualifier;
  5. import org.springframework.boot.context.properties.ConfigurationProperties;
  6. import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.context.annotation.Primary;
  10. import org.springframework.jdbc.core.JdbcTemplate;
  11. import org.springframework.transaction.jta.JtaTransactionManager;
  12. import javax.sql.DataSource;
  13. import javax.transaction.UserTransaction;
  14. import java.util.Properties;
  15. /**
  16. * @author lvlianqi
  17. * @description
  18. * @date 2022/3/7
  19. */
  20. @Configuration
  21. public class DBAtomikosConfig {
  22. //--------------------数据源1--------------------
  23. @ConfigurationProperties(prefix = "spring.datasource.test1")
  24. @Bean
  25. public Properties testOneProperties() {
  26. return new Properties();
  27. }
  28. @Bean(name = "testOneDataSource")
  29. @Primary
  30. public DataSource testOneDataSource() {
  31. AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
  32. Properties prop = testOneProperties();
  33. ds.setXaDataSourceClassName("com.mysql.cj.jdbc.MysqlXADataSource");
  34. ds.setUniqueResourceName("testOne");
  35. ds.setXaProperties(prop);
  36. return ds;
  37. }
  38. @Bean
  39. @Primary
  40. public JdbcTemplate testOneJdbcTemplate(@Qualifier("testOneDataSource") DataSource dataSource) {
  41. return new JdbcTemplate(dataSource);
  42. }
  43. //--------------------数据源2--------------------
  44. @ConfigurationProperties(prefix = "spring.datasource.test2")
  45. @Bean
  46. public Properties testTwoProperties() {
  47. return new Properties();
  48. }
  49. @Bean(name = "testTwoDataSource")
  50. public DataSource testTwoDataSource() {
  51. AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
  52. Properties prop = testTwoProperties();
  53. ds.setXaDataSourceClassName("com.mysql.cj.jdbc.MysqlXADataSource");
  54. ds.setUniqueResourceName("testTwo");
  55. ds.setXaProperties(prop);
  56. return ds;
  57. }
  58. @Bean
  59. public JdbcTemplate testTwoJdbcTemplate(@Qualifier("testTwoDataSource") DataSource dataSource) {
  60. return new JdbcTemplate(dataSource);
  61. }
  62. //--------------------配置spring的JtaTransactionManager,底层委派给atomikos进行处理--------------------
  63. @Bean
  64. public JtaTransactionManager jtaTransactionManager () {
  65. UserTransactionManager userTransactionManager = new UserTransactionManager();
  66. UserTransaction userTransaction = new UserTransactionImp();
  67. return new JtaTransactionManager(userTransaction, userTransactionManager);
  68. }
  69. }

4.测试事务类 TestAtomikos.java

  1. package com.llq.atomikos.service;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.beans.factory.annotation.Qualifier;
  4. import org.springframework.jdbc.core.JdbcTemplate;
  5. import org.springframework.stereotype.Service;
  6. import org.springframework.transaction.annotation.Transactional;
  7. /**
  8. * @author lvlianqi
  9. * @description
  10. * @date 2022/3/7
  11. */
  12. @Service
  13. public class TestAtomikos implements ITest{
  14. @Qualifier("testOneJdbcTemplate")
  15. @Autowired
  16. private JdbcTemplate testOneJdbcTemplate;
  17. @Qualifier("testTwoJdbcTemplate")
  18. @Autowired
  19. private JdbcTemplate testTwoJdbcTemplate;
  20. /**
  21. * 测试正常情况
  22. */
  23. @Transactional(rollbackFor = Exception.class, value = "jtaTransactionManager")
  24. public void test() {
  25. testOneJdbcTemplate.execute("insert into user (name, age) values ('张三', 18);");
  26. testTwoJdbcTemplate.execute("insert into user (name, age) values ('李四', 20);");
  27. }
  28. /**
  29. * 测试异常情况
  30. */
  31. @Transactional(rollbackFor = Exception.class, value = "jtaTransactionManager")
  32. public void testByException() {
  33. testOneJdbcTemplate.execute("insert into user (name, age) values ('张三', 18);");
  34. testTwoJdbcTemplate.execute("insert into user (name, age) values ('李四', 20);");
  35. int i = 1/0;
  36. }
  37. }

5.测试 SpringbootAtomikosApplicationTests.java

  1. //使用atomikos
  2. private static Class CLS = TestAtomikos.class;
  3. @Autowired
  4. ApplicationContext applicationContext;
  5. @Test
  6. public void testByException() {
  7. ITest test = (ITest) applicationContext.getBean(CLS);
  8. test.testByException();
  9. }

测试结果

执行错误



数据库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. ApacheCN 数据库译文集 20211112 更新

    创建你的 Mysql 数据库 零.前言 一.介绍 MySQL 设计 二.数据采集 三.数据命名 四.数据分组 五.数据结构调整 六.补充案例研究 Redis 学习手册 零.序言 一.NoSQL 简介 ...

  2. Serverless Workflow项目

    维基百科对工作流的定义是:对工作流程及其各操作步骤之间业务规则的抽象.概括描述.我们认为工作流的主要职责是: 保证结果一致性,提高容错性要求:对错误重试,捕获,执行回滚或补偿逻辑 为长时间运行的流程维 ...

  3. C++/WinUI 3 技术笔记(一)

    微软在 Windows 10 Version 1809 上正式发布了新的 UI 框架,命名为 WinUI 3. 这已经是微软发布的第不知道多少个 UI 框架了,但是微软宣称它将支持原生 C++ 和 W ...

  4. python编写购物车

    上次的学习又没有坚持下来,工作忙的不可开交,但我反思了一下还是自己没有下定决心好好学习,所以这次为期3个月的学习计划开始了,下面是这次学习后重新编写的购物车初版代码. 1 # 功能要求: 2 # 要求 ...

  5. JAVA_HOME环境的配置

    JAVA_HOME环境的配置 有时候可能需要更换Jdk的目录,但是经常修改path的值可能会不小心修改其他的路径,解决方法: 1.  创建一个JAVA_HOME的变量. 2.  JAVA_HOME的值 ...

  6. Eclipse不能启动,提示:The Eclipse executable launcher was unable to locate its companion launcher jar

    原因分析:JDK版本与eclipse不匹配 如jdk和eclipse版本号必须统一,64位都是64位,32位都是32位. jdk版本可以用命令,cmd进入命令窗口,然后输入java -version, ...

  7. 样式操作案例5-改变box的大小和位置

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. node.js 使用domain模块捕获异步回调中的异常

    和其他服务器端语言相比,貌似node.js 对于异常捕捉确实非常困难. 首先你会想到try/catch ,但是在使用过程中我们会发现并没有真正将错误控制在try/catch 语句中. 为什么? 答案是 ...

  9. c++ 子类与父类之间的类型转换

    子类与父类之间的类型转换 先给一段代码 class Base { public: int a = 10; }; class pub_Derv : public Base { Base *getBase ...

  10. Spring MVC项目快速搭建(编程模型)

    1)配置DispatcherServlet前端控制器(web配置) 2)将xml文件路径告诉Spring MVC(DispatcherServlet) 以上两步等价于继承了WebApplication ...