欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

所以就在一個service方法中加入了@Transaction,方法中包含了對兩個庫的操作。

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(); #報錯
    }    
}

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

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

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

@Transactional執(zhí)行流程

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

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

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

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

我們在上面了解到,因為@Transactional會創(chuàng)建事務(wù)然后獲得數(shù)據(jù)源,因為我們service方法上沒有@DS注解,就拿了默認(rèn)數(shù)據(jù)源,并且在這之后,這個事務(wù)信息會通過threadLocal跟當(dāng)前線程綁定,事務(wù)信息包括了connection連接,也就意味著,在進(jìn)入這個service方法的時候,當(dāng)前事務(wù)就綁定了數(shù)據(jù)源a,在運行到bMapper.save()時,因為connection已經(jīng)存在,所以拿到的數(shù)據(jù)源還是a,這時候就找不到b庫里的表了。

解決方法

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

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

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

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

總結(jié)

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

相關(guān)文章

  • 如何利用postman完成JSON串的發(fā)送功能(springboot)

    如何利用postman完成JSON串的發(fā)送功能(springboot)

    這篇文章主要介紹了如何利用postman完成JSON串的發(fā)送功能(springboot),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java實例化的幾種方法總結(jié)

    Java實例化的幾種方法總結(jié)

    這篇文章主要介紹了Java實例化的幾種方法總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • JAVA利用泛型返回類型不同的對象方法

    JAVA利用泛型返回類型不同的對象方法

    下面小編就為大家?guī)硪黄狫AVA利用泛型返回類型不同的對象方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • Mybatis-plus:${ew.sqlselect}用法說明

    Mybatis-plus:${ew.sqlselect}用法說明

    這篇文章主要介紹了Mybatis-plus:${ew.sqlselect}用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 詳解Java中布隆過濾器(Bloom Filter)原理及其使用場景

    詳解Java中布隆過濾器(Bloom Filter)原理及其使用場景

    布隆過濾器是1970年由布隆提出的,它實際上是一個很長的二進(jìn)制向量和一系列隨機映射函數(shù),它的作用是檢索一個元素是否存在我們的集合之中,本文給大家詳細(xì)的講解一下布隆過濾器,感興趣的同學(xué)可以參考閱讀
    2023-05-05
  • Spring IOC 能降低耦合的問題分析及解決方法

    Spring IOC 能降低耦合的問題分析及解決方法

    這篇文章主要介紹了Spring IOC 為什么能降低耦合,依賴注入是調(diào)用者僅通過聲明某個組件就可以獲得組件的控制權(quán),而對該組件的依賴關(guān)系管理、查找、加載由外部完成,需要的朋友可以參考下
    2022-06-06
  • spring boot中內(nèi)嵌redis的使用方法示例

    spring boot中內(nèi)嵌redis的使用方法示例

    這篇文章主要給大家介紹了關(guān)于spring boot中內(nèi)嵌redis使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-06-06
  • java中常用的字符串的比較方法(兩種)

    java中常用的字符串的比較方法(兩種)

    本文主要介紹了java中兩種常用的字符串的比較方法。具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • struts2入門(搭建環(huán)境、配置、示例)詳解

    struts2入門(搭建環(huán)境、配置、示例)詳解

    這篇文章主要介紹了struts2入門(搭建環(huán)境、配置、示例)詳解,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Maven忽略單元測試及打包到Nexus的實現(xiàn)

    Maven忽略單元測試及打包到Nexus的實現(xiàn)

    我們的工程在打包發(fā)布時候,通常都需要忽略單元測試,以免因環(huán)境原因,無法通過單元測試而影響發(fā)布,本文主要介紹了Maven忽略單元測試及打包到Nexus的實現(xiàn),感興趣的可以了解一下
    2024-04-04

最新評論