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

聊聊@DSTransactional的坑

为什么写这篇文章

最近项目里面使用了多数据源功能,使用的包是

<dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.1</version></dependency>

使用过程中就出现一个问题,在一个@DSTransactional注解里面标注的方法,前面插入的数据后面却查不出来。经过一番测试,终于找到问题的根源,特此记录以备后续查阅

问题复现

配置如下

spring:datasource:dynamic:primary:yrtstrict:falsedatasource:yrt:url:xxxusername:xxxpassword:xxxent:url:xxxusername:xxxpassword:xxx

为了打印数据源切换的日志,还增加了如下配置

logging:config:classpath:logback.xmllevel:org.springframework.transaction:DEBUGorg.springframework.jdbc.datasource:DEBUGcom.baomidou.dynamic.datasource:DEBUG

坑描述

写了@DS和没写@DS的类中的方法,@DS("primary")@DS("yrt"),即使primary对应的数据库就是yrt也会导致事务切换,事务切换就意味着前面插入的代码在后面无法查询,下面给出列子

代码描述

DsTransactionalTest

publicclassDsTransactionalTest{@AutowiredDsTransactionalTestServicedsTransactionalTestService;@org.junit.TestpublicvoidtestDsTransactional(){dsTransactionalTestService.dsTransactionalTest();}}

DsTransactionalTestService

@Service@AllArgsConstructorpublicclassDsTransactionalTestService{privatefinalVendorMPServicevendorMPService;privatefinalDealerMPServicedealerMPService;@DSTransactionalpublicvoiddsTransactionalTest(){Integervid=40048;vendorMPService.saveTest(vid);dealerMPService.testQueryVendor(vid);}}

VendorMPService

@ServicepublicclassVendorMPServiceextendsServiceImpl<VendorMPMapper,VendorMP>{publicvoidsaveTest(Integervid){VendorMPvendorMP=newVendorMP();vendorMP.setVendorInnerSn(vid);vendorMP.setName("测试厂商"+vid);// 省略其他字段this.save(vendorMP);}}

DealerMPService

@Service@AllArgsConstructor@DS("primary")publicclassDealerMPServiceextendsServiceImpl<DealerMPMapper,DealerMP>{privatefinalVendorMPServicevendorMPService;publicvoidtestQueryVendor(Integervid){System.out.println("厂商信息:"+vendorMPService.getById(vid));}}

此时安装我们的理解,应该后面要能查询出来数据才对,但运行结果如下

虽然有inser语句,但是并没有查询出来数据,那么此时我们来修改代码,把@DS("primary")也在VendorMPService上面新增一份,就能查出来数据了

@Service@DS("primary")publicclassVendorMPServiceextendsServiceImpl<VendorMPMapper,VendorMP>{// 省略}


我比较懒篇幅所限,另一种情况,一个标注的是@DS("primary"),另一个标注的是@DS("yrt"),即使primary对应的数据源就是yrt也是跟上面的情况是一样的,这里就不贴代码了。

回滚情况

我测试过程中,如果在后面的方法报错,前面的插入会回滚,即使一个标注的是@DS("primary"),另一个标注的是@DS("yrt"),或者一个标注了@DS("primary")另一个没标,都会回滚,也就是说:查询的时候虽然查询不出来,但是报错时能正常回滚。这就很奇怪,猜测是虽然有事务的切换,但是事务的ID是一样的,所以本质上还是同一个事务。

总结或最佳实践

  1. 理论上不要出现前面插入后面又查询是最好,直接把插入的对象传值到后面就行了,但是在实际项目大了以后,方法之间的调用错综复杂,有时候会经常出现开发某个新方法,但是有部分逻辑过于复杂进而直接调用的情况,如果项目对@DSTransactional@DS注解的使用不够熟练,没有做好规定,很容易会引发这个BUG。
  2. 对于@DS的使用,要规范团队统一使用如@DS("primary"), 并且对于领域范围确定的service, 都要标注这个@DS("primary"),不要一部分标注一部分不标,这样应该可以减少BUG
  3. 千万不要在@DSTransactional里面调用@Transactional标注的方法,两种注解混着用,得到的结果很奇怪,我目前还没测出会有什么奇怪的情况~,但是不要混着用时对的。
  4. 非必要时不要使用@DSTransactional,如果在某个方法里面需要新增A数据库的数据,然后查询B数据库的数据,此时直接给方法标注为@Transactional然后在查询B数据库的时候,使用@Transactional(propagation = Propagation.NOT_SUPPORTED, rollbackFor = Exception.class),即事务不传播。
http://www.jsqmd.com/news/502742/

相关文章:

  • MedGemma Medical Vision Lab支撑AI伦理研究:非诊断场景下医学影像理解边界实证分析
  • ModuleNotFoundError: No module named ‘moviepy.editor‘,安装了的,版本不对
  • UN R155与ISO 21434:汽车信息安全法规与标准的协同实践指南
  • 2025年-2026年好用的美容仪品牌推荐:基于多场景实测评价,解决抗衰与操作复杂核心痛点 - 外贸老黄
  • DeepChat跨平台部署指南:环境配置与开发/生产环境搭建
  • BUUCTF[ACTF2020 新生赛]Exec 1漏洞分析与实战利用
  • 从零开始:5分钟极速部署AI文本生成平台的实用指南
  • 2025年-2026年好用的大排灯品牌推荐:光疗技术趋势横向排名,涵盖日常护肤与急救场景核心痛点 - 外贸老黄
  • 【单片机论文写作模版】基于单片机的家庭智能花卉养护系统
  • AgentCPM实战教程:从零开始生成一份深度研究报告
  • 查重全红、AI率飙至90%?别慌!2026降AI保姆级攻略与工具实测来救命
  • 宽带任意阶贝塞尔光束生成:超表面技术与FDTD仿真实践
  • 高德地图JS API限流机制详解:从CUQPS_HAS_EXCEEDED_THE_LIMIT错误看如何合理使用地图服务
  • 如何用贪心算法解决二次分配问题?一个C++实现案例
  • EDK II固件开发实战:掌握UEFI系统架构的3大核心技术
  • 小白也能玩转GPT-OSS:20B:一键部署开源大模型全流程
  • 命令行.bat乱码实践-失败
  • 11kw OBC 三相PFC仿真模型及其技术应用
  • 告别重复编码,用快马ai一键生成c++文件处理工具提升工作效率
  • Python实战:用Scapy模拟ICMP Flood攻击(附完整代码解析)
  • 如何用Black-Litterman模型实现智能投资组合优化:PyPortfolioOpt实战指南
  • 提升 Coze Studio 开发效率:镜像源优化与依赖管理实战
  • 高效调试Java Stream链的8种技巧
  • Fish-Speech 1.5 本地部署避坑指南:从模型下载到语音生成的完整流程
  • Turbo Intruder深度解析:掌握Burp Suite高性能HTTP攻击扩展的10个核心技术点
  • 四相机测量项目源码:海康相机SDK+C#+halcon,通俗易懂,四种测量模式
  • Jvm-类加载机制
  • Comsol超材料S参数反演等效参数 负折射率超材料等效折射率、阻抗、介电常数与磁导率求解
  • 最受欢迎的Python Web开发框架推荐!
  • OpenWRT路由秒变USB共享中心:用USB/IP远程挂载打印机/摄像头的实战教程