JTA分布式事务管理器
XA协议:是一种标准协议,允许事务管理器协调多个资源管理器,确保在分布式事务中的一致性和原子性。
JTA:是JavaEE规范中的一种,用于管理分布式事务的 API,提供了事务的控制和协调机制
Atomikos理解成JTA的实现
XA是JTA的基础(JTA实现了XA协议) Atomikos实现了JTA
Atomikos这种方式限定与单应用多数据源使用场景.
关于理论的一些:
当业务操作需要涉及到多个数据库时,这就可称为分布式事务处理.实现分布式事务处理的关键是采用一种手段保证事务涉及的所有数据库所做的全部动作要么全部生效,要买么全部回滚.
目前处理分布式事务的规范就是XA规范.
X/Open组织为分布式事务制定了的事务中间件与数据库之间的接口规范.这种规范就是XA规范.事务中间件用它来通知数据库事务开始,提交,回滚等
X/Open组织仅仅制定了分布式事务处理的XA规范,但具体的实现则由不同的数据库厂商自行提供.
对于大部分主流商业及开源数据库都提供了XA规范的驱动
分布式事务处理方法很多
2PC 两阶段提交:
成功示例:

失败示例:


`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`content` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`user_id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
@Configuration
@MapperScan(basePackages = {"com.example.demo5.mapper"},sqlSessionFactoryRef = "primarySqlSessionFactory")
public class DataSourceConfig1 {@Primary@Bean(name="primaryDataSource")@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource(){//return DataSourceBuilder.create().build();//return new HikariDataSource();return new DruidDataSource();}@Primary@Bean(name="primarySqlSessionFactory")public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean bean=new SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setTypeAliasesPackage("com.example.demo5.pojo");bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*Mapper.xml"));SqlSessionFactory sqlSessionFactory = bean.getObject();sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);//sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);return sqlSessionFactory;}@Primary@Bean(name="primarySqlSessionTemplate")public SqlSessionTemplate primarySqlSessionTemplate(@Qualifier("primarySqlSessionFactory")SqlSessionFactory sqlSessionFactory){return new SqlSessionTemplate(sqlSessionFactory);}@Primary@Bean(name="primaryJdbcTemplate")public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource")DataSource dataSource){return new JdbcTemplate(dataSource);}@Primary@Bean(name="primaryTransactionManager")public DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource")DataSource dataSource){return new DataSourceTransactionManager(dataSource);}}
@Configuration
@MapperScan(basePackages = {"com.example.demo5.mapper2"},sqlSessionFactoryRef = "secondSqlSessionFactory")
public class DataSourceConfig2 {@Bean(name="secondDataSource")@ConfigurationProperties(prefix = "spring.datasource.second")public DataSource secondDataSource(){return DataSourceBuilder.create().build();}@Bean(name="secondSqlSessionFactory")public SqlSessionFactory secondSqlSessionFactory(@Qualifier("secondDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean bean=new SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setTypeAliasesPackage("com.example.demo5.pojo2");bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers2/*Mapper.xml"));SqlSessionFactory sqlSessionFactory = bean.getObject();sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);//sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);return sqlSessionFactory;}@Bean(name="secondSqlSessionTemplate")public SqlSessionTemplate secondSqlSessionTemplate(@Qualifier("secondSqlSessionFactory")SqlSessionFactory sqlSessionFactory){return new SqlSessionTemplate(sqlSessionFactory);}@Bean(name="secondJdbcTemplate")public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource")DataSource dataSource){return new JdbcTemplate(dataSource);}@Bean(name="secondTransactionManager")public DataSourceTransactionManager secondTransactionManager(@Qualifier("secondDataSource")DataSource dataSource){return new DataSourceTransactionManager(dataSource);}
} 

实体类


service


serviceImpl


事务测试

但是这两个事务管理器无法满足分布式事务
就是说我要将A数据库和B数据库的操作放在一个事务中,无法满足
Atomikos的数据源必须是AtomikosDataSourceBean,因此配置的数据源必须是XADatasource
然后再使用AtomikosDataSourceBean包装它们


使用Atomikos
Atomikos的数据源必须是AtomikosDataSourceBean,因此配置数据源必须先使用XADatasource,
然后再使用AtomikosDataSourceBean包装他们.
将不同数据源对应的AtomikosDataSourceBean注入对应sqlSessionFactory
application.properties

两个配置文件
@Configuration
@MapperScan(basePackages = {"com.example.demo5.mapper"},sqlSessionFactoryRef = "primarySqlSessionFactory")
public class DataSourceConfig1 {// @Primary@Bean(name="primary")@ConfigurationProperties(prefix = "spring.datasource.primary")public XADataSource primary(){//MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();//application.properties中的要与他里面的属性对应//return mysqlXADataSource;DruidXADataSource druidXADataSource=new DruidXADataSource();return druidXADataSource;}@Bean(name="primaryDataSource")@Primarypublic DataSource primaryDataSource(){AtomikosDataSourceBean atomikosDataSourceBean=new AtomikosDataSourceBean();atomikosDataSourceBean.setXaDataSource(primary());atomikosDataSourceBean.setMaxPoolSize(20);atomikosDataSourceBean.setUniqueResourceName("mysqlDs1");//取个唯一名字return atomikosDataSourceBean;}@Primary@Bean(name="primarySqlSessionFactory")public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean bean=new SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setTypeAliasesPackage("com.example.demo5.pojo");bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*Mapper.xml"));SqlSessionFactory sqlSessionFactory = bean.getObject();sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);//sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);return sqlSessionFactory;}@Primary@Bean(name="primarySqlSessionTemplate")public SqlSessionTemplate primarySqlSessionTemplate(@Qualifier("primarySqlSessionFactory")SqlSessionFactory sqlSessionFactory){return new SqlSessionTemplate(sqlSessionFactory);}@Primary@Bean(name="primaryJdbcTemplate")public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource")DataSource dataSource){return new JdbcTemplate(dataSource);}//使用JTA全局事务管理器后,不要再自定义事务管理器
// @Primary
// @Bean(name="primaryTransactionManager")
// public DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource")DataSource dataSource){
// return new DataSourceTransactionManager(dataSource);
// }} @Configuration
@MapperScan(basePackages = {"com.example.demo5.mapper2"},sqlSessionFactoryRef = "secondSqlSessionFactory")
public class DataSourceConfig2 {// @Primary@Bean(name="second")@ConfigurationProperties(prefix = "spring.datasource.second")public XADataSource second(){
// MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();//application.properties中的要与他里面的属性对应
//
// return mysqlXADataSource;DruidXADataSource druidXADataSource=new DruidXADataSource();return druidXADataSource;}@Bean(name="secondDataSource")public DataSource secondDataSource(){AtomikosDataSourceBean atomikosDataSourceBean=new AtomikosDataSourceBean();atomikosDataSourceBean.setXaDataSource(second());atomikosDataSourceBean.setMaxPoolSize(20);atomikosDataSourceBean.setUniqueResourceName("mysqlDs2");//取个唯一名字return atomikosDataSourceBean;}@Bean(name="secondSqlSessionFactory")public SqlSessionFactory secondSqlSessionFactory(@Qualifier("secondDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean bean=new SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setTypeAliasesPackage("com.example.demo5.pojo2");bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers2/*Mapper.xml"));SqlSessionFactory sqlSessionFactory = bean.getObject();sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);//sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL);return sqlSessionFactory;}@Bean(name="secondSqlSessionTemplate")public SqlSessionTemplate secondSqlSessionTemplate(@Qualifier("secondSqlSessionFactory")SqlSessionFactory sqlSessionFactory){return new SqlSessionTemplate(sqlSessionFactory);}@Bean(name="secondJdbcTemplate")public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource")DataSource dataSource){return new JdbcTemplate(dataSource);}// @Bean(name="secondTransactionManager")
// public DataSourceTransactionManager secondTransactionManager(@Qualifier("secondDataSource")DataSource dataSource){
// return new DataSourceTransactionManager(dataSource);
// }
} 
<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.3.0</version></dependency><!--stomikos--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jta-atomikos</artifactId></dependency><!--德鲁伊--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.15</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId> <!-- <scope>runtime</scope>使用MysqlXADataSource的话把运行时去掉,不然找不到 不用可以恢复运行时--></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter-test</artifactId><version>3.0.2</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>
相关文章:
JTA分布式事务管理器
XA协议:是一种标准协议,允许事务管理器协调多个资源管理器,确保在分布式事务中的一致性和原子性。 JTA:是JavaEE规范中的一种,用于管理分布式事务的 API,提供了事务的控制和协调机制 Atomikos理解成JTA的实现 XA是JTA的基础(JT…...
晨控CK-GW08系列网关控制器与CODESYS软件MODBUSTCP通讯手册
晨控CK-GW08系列是一款支持标准工业通讯协议ModbusTCP的网关控制器,方便用户集成到PLC等控制系统中。系统还集成了8路读写接口,用户可通过通信接口使用Modbus TCP协议对8路读写接口所连接的读卡器进行相对独立的读写操作。 晨控CK-GW08系列网关控制器适用于本公司多…...
读书笔记——labuladong算法笔记
读书笔记——labuladong算法笔记 序言计算机算法世界观计算机算法方法论二叉树遍历广度遍历BFS二叉树的前中后序遍历回溯算法动态规划算法二分搜索算法 其他算法滑动窗口双指针Union-Find算法 序言 labuladong算法笔记是一本讲解算法题求解技巧的书。本次读书笔记为2023年8月第…...
Linux中阶教程:bash shell基础
文章目录 输入输出赋值和计算条件判断函数for 循环数组及其遍历其他控制语句 输入输出 echo表示打印字符串;read表示获取用户输入;$用于引用变量。 # test1.sh bash中用#进行单行注释 echo "input your name:" read user_name echo "h…...
Golang 编译原理
简介 Golang(Go语言)是一种开源的编程语言,由Google开发并于2009年首次发布。它具备高效、可靠的特性,被广泛应用于云计算、分布式系统、网络服务等领域。Golang的编译原理是理解和掌握这门语言的重要基础之一。本文将介绍Golang…...
基于深度学习的动物识别 - 卷积神经网络 机器视觉 图像识别 计算机竞赛
文章目录 0 前言1 背景2 算法原理2.1 动物识别方法概况2.2 常用的网络模型2.2.1 B-CNN2.2.2 SSD 3 SSD动物目标检测流程4 实现效果5 部分相关代码5.1 数据预处理5.2 构建卷积神经网络5.3 tensorflow计算图可视化5.4 网络模型训练5.5 对猫狗图像进行2分类 6 最后 0 前言 &#…...
计算机视觉基础——基于yolov5-face算法的车牌检测
文章目录 车牌检测算法检测实现1.环境布置2.数据处理2.1 CCPD数据集介绍2.1.1 ccpd2019及20202.1.2 文件名字解析 2.2数据集处理2.2.1 CCPD数据处理2.2.2 CPRD数据集处理 2.3 检测算法2.3.1 数据配置car_plate.yaml2.3.2 模型配置2.3.3 train.py2.3.4 训练结果 2.4 部署2.4.1 p…...
【好书推荐】AI时代架构师修炼之道:ChatGPT让架构师插上翅膀
目录 前言 ChatGPT对架构师工作的帮助 快速理解和分析需求 提供代码建议和解决方案 辅助系统设计和优化 提高团队协作效率 如何使用ChatGPT提高架构师工作效率 了解用户需求和分析问题 编码实践和问题解决 系统设计和优化建议 团队协作和沟通效率提升 知识管理和文…...
全局代理和局部代理的区别
在计算机领域中,代理是一种常见的网络技术,它可以帮助用户更好地控制网络访问和数据传输。代理可以分为全局代理和局部代理两种,它们有着不同的作用和适用场景。 一、全局代理 全局代理指的是在系统级别设置的代理,它可以代理所…...
基于EPICS stream模块的直流电源的IOC控制程序实例
本实例程序实现了对优利德UDP6720系列直流电源的网络控制和访问,先在此介绍这个项目中使用的硬件: 1、UDP6721直流电源:受控设备 2、moxa串口服务器5150:将UDP6721直流电源设备串口连接转成网络连接 3、香橙派Zero3:运…...
Unity3D ECS架构适合作为主架构还是局部架构
前言 前言 Unity3D是一款广泛应用于游戏开发的跨平台游戏引擎,提供了丰富的功能和工具来简化游戏开发的过程。而Entity-Component-System(ECS)架构则是一种面向数据的设计模式,它将游戏对象(Entity)分解为…...
从零开始的目标检测和关键点检测(三):训练一个Glue的RTMPose模型
从零开始的目标检测和关键点检测(三):训练一个Glue的RTMPose模型 一、重写config文件二、开始训练三、ncnn部署 从零开始的目标检测和关键点检测(一):用labelme标注数据集 从零开始的目标检测和关键点检测…...
Qt6 中弹出消息框,一段时间后自动退出
以下代码功能,弹出模态消息框,然后,等待 3 秒,消息框自动退出 QMessageBox msgbox;msgbox.setText("sleep 3s");QTimer::singleShot(3000, &msgbox, &QMessageBox::close);msgbox.exec();...
elementUI树节点全选,反选,半选状态
// <template>部分 <div class"check-block"><el-divider></el-divider><el-checkbox :indeterminate"indeterminate" v-model"checkAll" change"handleCheckAllChange">全选</el-checkbox><e…...
Kafka、RabbitMQ、RocketMQ中间件的对比
消息中间件现在有不少,网上很多文章都对其做过对比,在这我对其做进一步总结与整理。 RocketMQ 淘宝内部的交易系统使用了淘宝自主研发的Notify消息中间件,使用Mysql作为消息存储媒介,可完全水平扩容,为了进一步降低成…...
Mac 创建并使用 .zshrc 文件
1,打开终端输入指令 touch .zshrc 2,你可能希望将 .bash_profile 文件中的内容复制到 .zshrc 文件中,那建议复制过来。 3,使用 .zshrc 文件 执行以下指令: source .zshrc 注:以后希望使用 .bash_prof…...
Unity3D移动开发如何依据性能选择Shader
前言 在Unity3D移动开发中,选择合适的Shader是非常重要的,它直接影响到游戏的性能和画面效果。本文将介绍如何依据性能选择Shader,并给出相应的技术详解以及代码实现。 对惹,这里有一个游戏开发交流小组,希望大家可以…...
基于stm32F4的智能宠物喂食器的设计:LVGL界面、定时喂食喂水通风
宠物喂食器 一、功能设计二、元器件选型三、UI设计四、原理图设计五、源代码设计六、成品展示 实物链接:https://m.tb.cn/h.5iCUX6H?tkPL65WXCEipQ CZ3457 一、功能设计 1、设计一个触摸屏作为人机交互 2、通过触摸屏设置时间定时喂食喂水通风 3、获取当前水槽的…...
jumpserver堡垒机docker方式安装部署
1、环境要求 请先自行创建 数据库 和 Redis, 版本要求参考上面环境要求说明 mysql>5.7 redis >5.0 2、创建数据库 mysql: create database jumpserver default charset utf8; GRANT ALL PRIVILEGES ON jumpserver.* TO jumpserver% IDENTIFIED BY nu4x599…...
在基于亚马逊云科技的湖仓一体架构上构建数据血缘的探索和实践
背景介绍 随着大数据技术的进步,企业和组织越来越依赖数据驱动的决策。数据的质量、来源及其流动性因此显得非常关键。数据血缘分析为我们提供了一种追踪数据从起点到终点的方法,有助于理解数据如何被转换和消费,同时对数据治理和合规性起到关…...
Java微服务在Istio中出现“偶发503 no healthy upstream”?7分钟定位Sidecar健康检查盲区与Liveness Probe冲突真相
第一章:Java微服务在Istio中偶发503问题的现象与影响在基于Istio构建的服务网格环境中,Java微服务(尤其是采用Spring Cloud Kubernetes或原生Spring Boot Istio Sidecar部署模式)频繁出现偶发性HTTP 503 Service Unavailable响应…...
LiuJuan20260223Zimage开箱体验:基于Z-Image LoRA,这个专精模型到底有多好用?
LiuJuan20260223Zimage开箱体验:基于Z-Image LoRA,这个专精模型到底有多好用? 你有没有遇到过这样的情况:想用AI画一个特定的人物,比如你故事里的主角,或者一个IP形象,但生成的图片要么不像&am…...
OpenCASCADE实战:如何正确获取3D模型面的法向(附完整代码示例)
OpenCASCADE实战:3D模型面法向的高效获取与方向校正 在三维建模与几何处理领域,准确获取模型表面的法向向量是许多高级操作的基础。无论是进行碰撞检测、光照计算还是有限元分析,法向数据的准确性直接影响最终结果的可靠性。OpenCASCADE作为一…...
告别台式机没麦克风的尴尬:用SonoBus+VB-Cable把手机秒变无线麦(保姆级配置)
台式机零成本无线麦克风方案:SonoBus与VB-Cable实战指南 你是否遇到过这样的尴尬时刻——台式电脑突然需要语音沟通,却发现没有麦克风?无论是紧急会议、游戏开黑还是直播互动,这种硬件缺失带来的困扰可能让你措手不及。本文将介绍…...
Arduino_Threads:Mbed OS平台的嵌入式多线程实践框架
1. Arduino_Threads 库深度解析:面向 Mbed OS 的嵌入式多线程实践框架1.1 库定位与工程价值Arduino_Threads 是 Arduino 官方为基于 Mbed OS 核心的 Arduino 开发板(如 Nano RP2040 Connect、Portenta H7、Nicla Sense ME 等)设计的轻量级多线…...
Git开源贡献全指南:从入门到精通
开源项目Git贡献全流程拆解 理解开源项目贡献的基本概念 开源项目的定义与意义Git在开源协作中的核心作用常见的开源贡献类型(代码、文档、测试等) 准备开发环境 安装Git并完成基础配置(用户名、邮箱、SSH密钥)注册GitHub/GitLab等…...
从 DEFINE VIEW 走向 DEFINE VIEW ENTITY:把 CDS View 迁移到 CDS View Entity 的方法、边界与实战心法
围绕 CDS View Entity 迁移这条主线,下面把概念演进、工具链、风险识别、手工改造要点以及项目落地策略完整梳理一遍。文章既适合还在维护传统 CDS DDIC-based view 的团队,也适合正在推进 S/4HANA、ABAP Cloud、RAP、Clean Core 的开发团队参考。 CDS View Entity 在 ABAP …...
抖音批量下载神器:免费一键收藏创作者全部作品
抖音批量下载神器:免费一键收藏创作者全部作品 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖音…...
002MCP
MCP...
2026年项目管理工具选型指南:功能对比、适用场景与避坑建议
项目管理工具早已不只是任务看板,而是连接目标、需求、计划、资源、交付、知识与复盘的管理底座。本文选取 ONES、Tower、Jira、Asana、monday.com、ClickUp、Microsoft Planner、Smartsheet、Notion 九款主流项目管理工具展开评估,帮助企业中高层研发负…...
