最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

@Transactional和@DS怎樣在事務(wù)中切換數(shù)據(jù)源

 更新時(shí)間:2023年07月31日 09:47:17   作者:Abstracted  
這篇文章主要介紹了@Transactional和@DS怎樣在事務(wù)中切換數(shù)據(jù)源問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

@Transactional和@DS在事務(wù)中切換數(shù)據(jù)源

在一次需求中,需要對(duì)兩個(gè)數(shù)據(jù)庫(kù)進(jìn)行讀寫(xiě)操作,并且要保證對(duì)這兩個(gè)庫(kù)的操作的原子性。

所以就在一個(gè)service方法中加入了@Transaction,方法中包含了對(duì)兩個(gè)庫(kù)的操作。

spring:
  datasource:
    dynamic:
      primary: A 
      datasource:
        A:
          url:..
          driver-class-name: com.mysql.jdbc.Driver
          username: root
          password:
        B:
          url: ..
          driver-class-name: com.mysql.jdbc.Driver
          username: root
          password:
        C:
          url: ..
          driver-class-name: com.mysql.jdbc.Driver
          username: root
          password:
@Mapper
@DS("A")
public interface AMapper{
      @Insert("insert into a ...")
      void save();
}
@Mapper
@DS("B")
public interface BMapper{
      @Insert("insert into b ...")
      void save();
}
public class aService{
@Autowired
private aMapper、bMapper、cMapper
    @Transactional
    public void save(){
	    aMapper.save();
	    bMapper.save(); #報(bào)錯(cuò)
    }    
}

在執(zhí)行測(cè)試時(shí)bMapper.save()發(fā)生了錯(cuò)誤,報(bào)錯(cuò)信息:找不到b表,很明顯sql是從A庫(kù)中找b表,當(dāng)然會(huì)報(bào)錯(cuò)找不到b表。

如果把@Transactional注解去掉就可以正常運(yùn)行,數(shù)據(jù)也成功分別寫(xiě)入兩個(gè)庫(kù)中。

但是我們命名已經(jīng)在2個(gè)Mapper上加了@Ds()注解來(lái)切換要是用的數(shù)據(jù)源,那為什么加入了事務(wù)就報(bào)錯(cuò)了呢?

@Transactional執(zhí)行流程

1、save方法添加了 @Transactional 注解,Spring 事務(wù)就會(huì)生效。此時(shí),Spring TransactionInterceptor 會(huì)通過(guò) AOP 攔截該方法,創(chuàng)建事務(wù)。而創(chuàng)建事務(wù),勢(shì)必就會(huì)獲得數(shù)據(jù)源。

  • 那么,TransactionInterceptor 會(huì)使用 Spring DataSourceTransactionManager 創(chuàng)建事務(wù),并將事務(wù)信息通過(guò) ThreadLocal 綁定在當(dāng)前線程。
  • 而事務(wù)信息,就包括事務(wù)對(duì)應(yīng)的 Connection 連接。那也就意味著,還沒(méi)走到 OrderMapper 的查詢操作,Connection 就已經(jīng)被創(chuàng)建出來(lái)了。
  • 并且,因?yàn)槭聞?wù)信息會(huì)和當(dāng)前線程綁定在一起,在 OrderMapper 在查詢操作需要獲得 Connection 時(shí),就直接拿到當(dāng)前線程綁定的 Connection ,而不是 OrderMapper 添加 @DS 注解所對(duì)應(yīng)的 DataSource 所對(duì)應(yīng)的 Connection 。

2、OK ,那么我們現(xiàn)在可以把問(wèn)題聚焦到 DataSourceTransactionManager 是怎么獲取 DataSource 從而獲得 Connection 的了。

  • 對(duì)于每個(gè) DataSourceTransactionManager 數(shù)據(jù)庫(kù)事務(wù)管理器,創(chuàng)建時(shí)都會(huì)傳入其需要管理的 DataSource 數(shù)據(jù)源。
  • 在使用 dynamic-datasource-spring-boot-starter 時(shí),它創(chuàng)建了一個(gè) DynamicRoutingDataSource ,傳入到 DataSourceTransactionManager 中。
  • DynamicRoutingDataSource 負(fù)責(zé)管理我們配置的多個(gè)數(shù)據(jù)源。例如說(shuō),本示例中就管理了 a、b兩個(gè)數(shù)據(jù)源,并且默認(rèn)使用 a 數(shù)據(jù)源。
  • 那么在當(dāng)前場(chǎng)景下,DynamicRoutingDataSource 需要基于 @DS 獲得數(shù)據(jù)源名,從而獲得對(duì)應(yīng)的 DataSource ,結(jié)果因?yàn)槲覀冊(cè)?Service 方法上,并沒(méi)有添加 @DS 注解,所以它只好返回默認(rèn)數(shù)據(jù)源,也就是 a 。故此,就發(fā)生了 找不到表 的異常。

我們?cè)谏厦媪私獾剑驗(yàn)锧Transactional會(huì)創(chuàng)建事務(wù)然后獲得數(shù)據(jù)源,因?yàn)槲覀僺ervice方法上沒(méi)有@DS注解,就拿了默認(rèn)數(shù)據(jù)源,并且在這之后,這個(gè)事務(wù)信息會(huì)通過(guò)threadLocal跟當(dāng)前線程綁定,事務(wù)信息包括了connection連接,也就意味著,在進(jìn)入這個(gè)service方法的時(shí)候,當(dāng)前事務(wù)就綁定了數(shù)據(jù)源a,在運(yùn)行到bMapper.save()時(shí),因?yàn)閏onnection已經(jīng)存在,所以拿到的數(shù)據(jù)源還是a,這時(shí)候就找不到b庫(kù)里的表了。

解決方法

把對(duì)B庫(kù)操作的方法都加上@DS和 @Transactional注解(在service上加)。

ps:在完成了aMapper.save()之后去調(diào)用bMapper.save()時(shí),一定要把@Transactional設(shè)置為Propagation.REQUIRES_NEW,這樣在調(diào)用另一個(gè)事務(wù)方法時(shí),TransactionInterceptor 會(huì)將原事務(wù)掛起,暫時(shí)性的將原事務(wù)信息和當(dāng)前線程解綁,然后創(chuàng)建一個(gè)新的事務(wù),并且從數(shù)據(jù)源中取出一個(gè)connection鏈接,而此時(shí)的數(shù)據(jù)源已經(jīng)被切換成我們需要的數(shù)據(jù)源。如果B操作發(fā)生了異常,B事務(wù)將回滾并將異常進(jìn)行拋出到A,A事務(wù)自然也會(huì)回滾。

在對(duì)B庫(kù)的操作如果不需要事務(wù)的話,可以在對(duì)B庫(kù)操作的方法上指定事務(wù)的隔離級(jí)別為NOT_SUPPORTED,這樣執(zhí)行到該方法時(shí)會(huì)暫停掛起當(dāng)前事務(wù),等待對(duì)B庫(kù)的方法執(zhí)行完畢再恢復(fù)事務(wù)。

pps:當(dāng)前事務(wù)方法里用this來(lái)調(diào)用另一個(gè)事務(wù)方法時(shí),當(dāng)前這個(gè)事務(wù)方法的@DS也會(huì)起作用,原因是@Ds是基于AOP切面在方法執(zhí)行前切換數(shù)據(jù)源,而this調(diào)用的不是通過(guò)代理生成的事務(wù)對(duì)象,而是自己本身的原對(duì)象,不會(huì)開(kāi)啟事務(wù)。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • springboot中一些比較常用的注解總結(jié)

    springboot中一些比較常用的注解總結(jié)

    今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著springboot中一些比較常用的注解展開(kāi),文中有非常詳細(xì)的總結(jié),需要的朋友可以參考下
    2021-06-06
  • SpringMVC對(duì)日期類型的轉(zhuǎn)換示例

    SpringMVC對(duì)日期類型的轉(zhuǎn)換示例

    本篇文章主要介紹了SpringMVC對(duì)日期類型的轉(zhuǎn)換示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-02-02
  • spring mvc中注解@ModelAttribute的妙用分享

    spring mvc中注解@ModelAttribute的妙用分享

    這篇文章主要給大家介紹了關(guān)于spring mvc中注解@ModelAttribute妙用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Android具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-09-09
  • 詳細(xì)介紹MyBatis 3.4.0版本的功能

    詳細(xì)介紹MyBatis 3.4.0版本的功能

    這篇文章主要給大家介紹了關(guān)于MyBatis 3.4.0版本的功能,文中只列舉部分重要的內(nèi)容,詳細(xì)內(nèi)容看官方說(shuō)明,需要的朋友可以參考借鑒,下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)吧。
    2017-06-06
  • 基于Spring Security的動(dòng)態(tài)權(quán)限系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)

    基于Spring Security的動(dòng)態(tài)權(quán)限系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)

    本文介紹一個(gè)基于Spring Boot 2.7.18和SpringSecurity實(shí)現(xiàn)的權(quán)限系統(tǒng),支持接口級(jí)權(quán)限控制,支持權(quán)限,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-07-07
  • Springboot中前端向后端傳遞數(shù)據(jù)的幾種方式

    Springboot中前端向后端傳遞數(shù)據(jù)的幾種方式

    在前端和后端的交互中,前端需要向后端傳遞數(shù)據(jù),常見(jiàn)的數(shù)據(jù)傳遞方式包括表單提交、URL參數(shù)、JSON請(qǐng)求等,本文將介紹常見(jiàn)的幾種數(shù)據(jù)傳遞方式,并說(shuō)明如何在SpringBoot中實(shí)現(xiàn)這些方式,需要的朋友可以參考下
    2025-08-08
  • Springboot分頁(yè)插件使用實(shí)例解析

    Springboot分頁(yè)插件使用實(shí)例解析

    這篇文章主要介紹了Springboot分頁(yè)插件使用實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • spring boot 使用@Async實(shí)現(xiàn)異步調(diào)用方法

    spring boot 使用@Async實(shí)現(xiàn)異步調(diào)用方法

    本篇文章主要介紹了spring boot 使用@Async實(shí)現(xiàn)異步調(diào)用方法,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-04-04
  • Java設(shè)計(jì)模式之狀態(tài)模式詳解

    Java設(shè)計(jì)模式之狀態(tài)模式詳解

    Java?中的狀態(tài)模式(State?Pattern)是一種行為型設(shè)計(jì)模式,它允許對(duì)象在內(nèi)部狀態(tài)發(fā)生改變時(shí)改變其行為,本文將詳細(xì)介紹?Java?中的狀態(tài)模式,我們將從狀態(tài)模式的概述、結(jié)構(gòu)與實(shí)現(xiàn)、優(yōu)缺點(diǎn)、適用場(chǎng)景等方面進(jìn)行講解,需要的朋友可以參考下
    2023-05-05
  • Java使用Apache POI操作Excel詳解

    Java使用Apache POI操作Excel詳解

    在Java中操作Excel是日常工作中經(jīng)常遇到的問(wèn)題,而Apache Poi是一種流行且廣泛使用的方式,它提供了各種庫(kù)和工具,所以本文就來(lái)詳細(xì)如何使用Apache Poi來(lái)進(jìn)行Excel文件操作吧
    2023-06-06

最新評(píng)論

遵化市| 达拉特旗| 都兰县| 白水县| 临猗县| 门头沟区| 红安县| 新龙县| 海原县| 双江| 安龙县| 桦南县| 昌图县| 呼玛县| 石景山区| 衡水市| 横峰县| 织金县| 平谷区| 蓬安县| 汝阳县| 喀喇沁旗| 镇宁| 铁岭市| 拉萨市| 巴青县| 南安市| 策勒县| 上林县| 土默特左旗| 团风县| 新巴尔虎左旗| 鄢陵县| 黄石市| 陕西省| 天等县| 泾源县| 翁牛特旗| 淮阳县| 阜阳市| 武功县|