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

SpringBoot 使用多SqlSessionFactory下的事务问题

如下配置了两个数据源:

spring:datasource:ds1:jdbc-url: jdbc:mysql://localhost:3307/spring-boot-demos?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: passwordds2:jdbc-url: jdbc:mysql://127.0.0.1:3308/spring-boot-demos?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: password

同时,配置了响应的数据源配置:

@Configuration
public class DataSourceConfigurations {@Configuration@MapperScan(basePackages = "com.example.mapper.ds1",sqlSessionFactoryRef = "ds1SqlSessionFactory")public static class Ds1Configuration {public static final String DS1_MAPPER_LOCATION = "classpath*:mapper/ds1/*.xml";@Primary@Bean("ds1DataSource")@ConfigurationProperties(prefix = "spring.datasource.ds1")public DataSource ds1DataSource() {return DataSourceBuilder.create().build();}@Primary@Bean("ds1TransactionManager")public PlatformTransactionManager ds1TransactionManager(@Qualifier("ds1DataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Primary@Bean(name = "ds1SqlSessionFactory")public SqlSessionFactory ds1SqlSessionFactory(@Qualifier("ds1DataSource") DataSource dataSource) throws Exception {MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();sessionFactoryBean.setDataSource(dataSource);sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(DS1_MAPPER_LOCATION));return sessionFactoryBean.getObject();}}@Configuration@MapperScan(basePackages = "com.example.ds2",sqlSessionFactoryRef = "ds2SqlSessionFactory")public static class Ds2Configuration {public static final String DS2_MAPPER_LOCATION = "classpath*:mapper/ds2/*.xml";@Bean@ConfigurationProperties(prefix = "spring.datasource.ds2")public DataSource ds2DataSource() {return DataSourceBuilder.create().build();}@Beanpublic PlatformTransactionManager ds2TransactionManager(@Qualifier("ds2DataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Bean(name = "ds2SqlSessionFactory")public SqlSessionFactory ds2SqlSessionFactory(@Qualifier("ds2DataSource") DataSource dataSource) throws Exception {MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();sessionFactoryBean.setDataSource(dataSource);sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(DS2_MAPPER_LOCATION));return sessionFactoryBean.getObject();}}
}

相对应的,有两个Mapper:

@Data
@TableName("tb_test1")
public class Test1DO {@TableIdprivate Integer id;private LocalDateTime createTime;private boolean deleted;private String name;private Short status;
}@Mapper
public interface Ds1Test1Mapper extends BaseMapper<Test1DO> {}@Mapper
public interface Ds2Test1Mapper extends BaseMapper<Test1DO> {}

首先,先向ds2数据库的tb_test1表中插入id=1的数据。然后做如下操作:

@RequiredArgsConstructor
@Service
public class Test1ServiceImpl implements ITest1Service {private final Ds1Test1Mapper ds1Test1Mapper;private final Ds2Test1Mapper ds2Test1Mapper;@Override@Transactional(rollbackFor = RuntimeException.class)public void save() {Test1DO test1DO = new Test1DO();test1DO.setId(1);test1DO.setName("test ds2");test1DO.setStatus((short) 1);ds1Test1Mapper.insert(test1DO);ds2Test1Mapper.insert(test1DO);}@Overridepublic void save1() {Test1DO test1DO = new Test1DO();test1DO.setId(1);test1DO.setName("test ds2");test1DO.setStatus((short) 1);ds1Test1Mapper.insert(test1DO);ds2Test1Mapper.insert(test1DO);}
}

当调用save1()时,ds1中插入了一条数据,而ds2中由于id冲突而失败。
如果调用save()时,ds1和ds2中都插入失败(ds1的数要清掉).
这个时候对save()进行断点:

//TransactionAspectSupport.java 377行 (springboot版本2.7.17)
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);

发现ptm是上面配置的Primary TransactionManager。

如果将两个数据库表数据都清空,然后执行save(),对 commit 进行断点:

// DataSourceTransactionManager.doCommit()
protected void doCommit(DefaultTransactionStatus status) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();Connection con = txObject.getConnectionHolder().getConnection();if (status.isDebug()) {logger.debug("Committing JDBC transaction on Connection [" + con + "]");}try {con.commit();}catch (SQLException ex) {throw translateException("JDBC commit", ex);}}

对 con 进行断点发现,其为3307的数据库的连接,然后整个过程没有别的连接了。并且3308的数据也能正常保存。

以上也就是两点:
1、当使用多个SqlSessionFactory配置数据源时,公用同一个TransactionManager,和同一个Connection(3307),这个时候,3308数据正常提交。
2、当提交3308的数据发生异常时,3307的数据也不会插入,即有事务属性。

目前对于上述两点不是很理解,为何只有3307的Connection,3308的数据也能提交,而且为何会有事务性。

可能是作者对SpringBoot的事务不是理解的很深入,希望有大佬能解惑。

相关文章:

SpringBoot 使用多SqlSessionFactory下的事务问题

如下配置了两个数据源&#xff1a; spring:datasource:ds1:jdbc-url: jdbc:mysql://localhost:3307/spring-boot-demos?serverTimezoneUTC&useUnicodetrue&characterEncodingutf8&useSSLfalse&allowPublicKeyRetrievaltrueusername: rootpassword: passwordd…...

浏览器内置NoSQL数据库IndexedDB

IndexedDB - 浏览器内容数据库 indexedDB 是一种浏览器内置的NoSQL数据库&#xff0c;它使用键值对存储数据&#xff0c;用于在客户端存储大量结构化数据。它支持离线应用程序和高效的数据检索&#xff0c;可以在 Web 应用程序中替代传统的 cookie 和 localStorage。 IndexDB是…...

网络参考模型与标准协议(二)-TCP/IP对等模型详细介绍

应用层 应用层为应用软件提供接口&#xff0c;使应用程序能够使用网络服务。应用层协议会指定使用相应的传输层协议&#xff0c;以及传输层所使用的端口等。TCP/IP每一层都让数据得以通过网络进行传输&#xff0c;这些层之间使用PDU ( Paket Data Unit,协议数据单元)彼此交换信…...

万宾科技智能井盖传感器,预防城市道路安全

随着城市交通的不断发展和城市化进程的加速推进&#xff0c;城市道路安全问题日益凸显。市政井盖作为城市道路的一部分&#xff0c;承担着重要的交通安全保障职责。然而传统的市政井盖管理方式存在许多不足。针对这些问题政府需要采取适当的措施&#xff0c;补足传统管理方式的…...

GCC/Make/CMake 工具链

阅读前可以思考的问题&#xff1a;&#xff08;答案在文章的最后面,小白可以略过&#xff09; GCC/Make/CMake是什么关系&#xff1f; 一个C程序编译为一个可执行文件&#xff0c;需要哪些过程&#xff1f; #include语句所引入的库&#xff0c;如何才能找到对应的完整源代码文…...

GO抽象工厂模式

既然工厂模式每个产品都需要实现对应的工厂类去生成相关实例&#xff0c;提取产品的共性&#xff0c;提高代码的内聚性&#xff0c; 就是抽象工厂模式要干的。在抽象工厂中&#xff0c;依然是不同产品对应不同的工厂类&#xff0c;但可以尽可能将具有相同共性的产品类别合在一起…...

Linux 磁盘/分区/修复 命令

目录 1. lsblk&#xff08;list block devices&#xff09; 2. fdisk&#xff08;fragment disk&#xff09; 3. gdisk 4. mkfs&#xff08;make filesystem&#xff09; 5. df&#xff08;display file-system disk space usage&#xff09; 6. du 7. fsck&#xff08;file-sy…...

php一句话木马免杀

php一句话木马免杀 针对于php一句话木马做免杀&#xff1a; 利用php动态函数的特性&#xff0c;将危险函数拆分成字符&#xff0c;最终使用字符串拼接的方式&#xff0c;然后重新拼接&#xff0c;后加括号执行代码&#xff0c;并且可以使用花指令进行包装&#xff0c;如无限i…...

深度学习人体跌倒检测 -yolo 机器视觉 opencv python 计算机竞赛

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习的人体跌倒检测算法研究与实现 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满…...

轻松整理文件夹,将视频文件全部归类到另一个文件夹!

如果你需要整理文件夹中的文件&#xff0c;将同一类别的文件归纳到一起&#xff0c;可以更加方便地管理和查找。现在&#xff0c;我们有一个简单而实用的方法&#xff0c;可以将文件夹中的所有视频文件归类到另一个文件夹中&#xff0c;让你的文件管理更加有序和高效。 首先&am…...

存储服务器特征是什么

存储服务器和普通服务器是有差别的&#xff0c;配置方式不同&#xff0c;因为存储服务器是为特定目标设计的&#xff0c;通常存储服务器是独立的单元&#xff0c;大多数时候是被设计成4U机架式&#xff0c;存储服务器一般是单机运作的&#xff0c;不与其他服务器连接。今天小编…...

Conditional GAN

Text-to-Image 对于根据文字生成图像的问题&#xff0c;传统的做法就是训练一个NN&#xff0c;然后输入一段文字&#xff0c;输出对应一个图片&#xff0c;输出图片与目标图片越接近越好。存在的问题就是&#xff0c;比如火车对应的图片有很多张&#xff0c;如果用传统的NN来训…...

OOM问题排查+Jvm优化

OOM问题排查&#xff1a; 1、top命令&#xff1a;查看cpu和内存的使用情况。 2、jstat命令&#xff1a;查看YGC和FGC情况&#xff0c;一般都是老年代不够用。导致OOM 3、jmap命令&#xff1a; 查看哪个类的实例过多,以每个类占用多少了内存。4、jstack 查看线程与线程之间的阻…...

链表:C++实现

引言&#xff1a; 链表是一种常见的数据结构&#xff0c;它由一系列节点组成&#xff0c;每个节点包含一个数据元素和一个指向下一个节点的指针。相比于数组&#xff0c;链表具有动态性和灵活性&#xff0c;可以高效地进行插入和删除操作&#xff0c;但是查找操作的时间复杂度较…...

使用JMX监控ZooKeeper和Kafka

JVM 默认会通过 JMX 的方式暴露基础指标,很多中间件也会通过 JMX 的方式暴露业务指标,比如 Kafka、Zookeeper、ActiveMQ、Cassandra、Spark、Tomcat、Flink 等等。掌握了 JMX 监控方式,就掌握了一批程序的监控方式。本节介绍 JMX-Exporter 的使用,利用 JMX-Exporter 把 JMX…...

蓝桥等考C++组别七级008

第一部分:选择题 1、C++ L7 (15分) 在判断是否满足循环条件之前,至少执行循环体语句一次的是哪种循环结构?( ) for循环while循环do-while循环以上都不是正确答案:C 2、C++ L7 (15分) 执行以下程序,会输出几个“*”?( ) for(int i = 0; i <= 10; i++){…...

sam和mobilesam导出预处理的onnx

一、前言 sam或者mobilesam的python推理都存在一些前处理,如下所示: sam.to(device=cuda) predictor = SamPredictor(sam) predictor.set_image(image) image_embedding = predictor.get_image_embedding().cpu().numpy() checkpoint = "./weights/mobile_sam.pt"…...

开源与闭源:大模型发展的双重走向

目录 前言开源和闭源的优劣势比较开源的优势闭源的优势 开源和闭源对大模型技术发展的影响对技术发展的影响对数据共享的影响对业务拓展的影响 开源与闭源的商业模式比较开源的商业模式闭源的商业模式 处在大模型洪流中&#xff0c;向何处去&#xff1f;结语 前言 随着人工智能…...

c# 逆变 / 协变

个人理解&#xff1a; 1. 逆变in向上兼容类 2. 协变out向下兼容类 在面向对象编程中&#xff0c;尤其是使用泛型时&#xff0c;in和out关键字用于限制类型参数的协变性和逆变性。 in关键字&#xff08;逆变&#xff09;&#xff1a; in关键字用于标记泛型类型参数的逆变性。…...

electron使用better-sqlite3打包失败(electron打包有进程没有界面)

remove *\chrome_100_percent.pak: Access is denied. 解决&#xff1a; 管理员权限执行&#xff1a;taskkill /IM 你的进程名.exe /F&#xff0c;再次执行build electron使用better-sqlite3打包后有进程没有界面 原因是代码及依赖包安装有误&#xff0c;模块丢失。主要分享的…...

GD32读保护设置后,我的代码还能自己更新吗?深入解析FMC选项字节的‘自操作’机制

GD32读保护机制深度剖析&#xff1a;如何在保护状态下实现安全自更新 当我们在GD32微控制器上启用读保护功能时&#xff0c;最常被问到的一个问题是&#xff1a;"我的程序还能自我更新吗&#xff1f;"这个看似简单的问题背后&#xff0c;隐藏着对Flash存储安全机制的…...

PHP魔术方法实战避坑:用MRCTF2020 Ezpop案例讲清楚__invoke和__get的冷门用法

PHP魔术方法高阶实战&#xff1a;从MRCTF2020 Ezpop看__invoke与__get的攻防艺术 在CTF竞赛和实际安全审计中&#xff0c;PHP魔术方法常常成为代码执行的"暗门"。大多数开发者熟悉__construct、__destruct等常见魔术方法&#xff0c;但对__invoke和__get这类相对冷门…...

FPM Master 进程接收连接,唤醒一个 Worker 进程。

真相是&#xff1a; Master 进程通常不直接接收业务连接&#xff08;除非配置了 listen.owner/group 且使用 Unix Socket&#xff0c;但即使如此&#xff0c;它也不处理 HTTP 协议&#xff09;。Master 进程绝不“唤醒” Worker 去处理请求。Worker 进程是常驻内存 (Resident) …...

手把手教你排查OpenWRT虚拟机网卡直通失败:从lspci到QEMU命令的避坑指南

手把手教你排查OpenWRT虚拟机网卡直通失败&#xff1a;从lspci到QEMU命令的避坑指南 虚拟化环境中实现网卡直通是许多网络爱好者和企业IT管理员追求的高性能解决方案。当你在Debian宿主机上尝试为OpenWRT虚拟机配置PCIe网卡直通时&#xff0c;可能会遇到各种意料之外的障碍——…...

iOS原生AI助手开发实战:从UIKit选型到Stable Diffusion本地部署

1. 项目概述&#xff1a;一个原生、全能的iOS端AI助手最近在App Store上架了一款名为“Chat走啦”的iOS应用&#xff0c;它本质上是一个功能相当全面的ChatGPT原生客户端。和很多基于WebView简单套壳的应用不同&#xff0c;这个项目从底层网络请求到上层UI交互&#xff0c;都采…...

不止是教学玩具:在浏览器里用MARIE模拟器调试你的第一个‘操作系统’内核

从零构建微型内核&#xff1a;在MARIE模拟器中探索操作系统核心机制 当我在大学第一次接触操作系统课程时&#xff0c;教授在黑板上画出的那些抽象概念——进程调度、内存管理、系统调用——总让我感到既神秘又遥不可及。直到有一天&#xff0c;我在一个仅有4K字内存的模拟器里…...

为什么选择vue-markdown?与其他Markdown渲染器的全面对比分析

为什么选择vue-markdown&#xff1f;与其他Markdown渲染器的全面对比分析 【免费下载链接】vue-markdown vue-markdown: 是一个用于Vue.js的Markdown渲染器组件&#xff0c;允许在Vue应用中轻松展示Markdown格式的内容。 项目地址: https://gitcode.com/gh_mirrors/vu/vue-ma…...

终极指南:dnSpyEx .NET调试与反编译工具的高效配置秘籍

终极指南&#xff1a;dnSpyEx .NET调试与反编译工具的高效配置秘籍 【免费下载链接】dnSpy Unofficial revival of the well known .NET debugger and assembly editor, dnSpy 项目地址: https://gitcode.com/gh_mirrors/dns/dnSpy 还在为调试没有源代码的.NET程序而烦恼…...

Obsidian Tasks 任务优先级终极指南:6个等级助你高效管理待办事项

Obsidian Tasks 任务优先级终极指南&#xff1a;6个等级助你高效管理待办事项 【免费下载链接】obsidian-tasks Task management for the Obsidian knowledge base. 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-tasks 在Obsidian知识管理系统中&#xff0c;T…...

终极指南:fastbook硬件加速GPU/TPU/FPGA优化策略与实战技巧

终极指南&#xff1a;fastbook硬件加速GPU/TPU/FPGA优化策略与实战技巧 【免费下载链接】fastbook The fastai book, published as Jupyter Notebooks 项目地址: https://gitcode.com/gh_mirrors/fa/fastbook fastbook作为深度学习领域的经典教程&#xff0c;其基于Jupy…...