国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

解決多數(shù)據(jù)源的事務問題 - 基于springboot--mybatis

這篇具有很好參考價值的文章主要介紹了解決多數(shù)據(jù)源的事務問題 - 基于springboot--mybatis。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

在Spring Boot和MyBatis中,我們有時需要在方法中同時使用兩個不同的數(shù)據(jù)庫,但使用@Transactional注解會變得復雜。這時我們可以用一種更靈活的方法來處理。

想象一下這樣的場景:我們有兩個數(shù)據(jù)庫,我們希望在一個方法中同時操作它們,但是普通的@Transactional注解變得不太適用。

我們可以采用一種類似于“雙提交”的策略來解決這個問題。首先,我們讓兩個數(shù)據(jù)庫執(zhí)行所需的操作,然后立即提交。接下來,如果整個方法執(zhí)行成功,我們就提交這兩個數(shù)據(jù)庫的事務。但是,如果在方法執(zhí)行過程中出現(xiàn)了問題,我們會回滾這兩個數(shù)據(jù)庫的事務。

簡單來說,我們先讓兩個數(shù)據(jù)庫做好準備,等到方法完成后,如果一切順利,我們正式確認這兩個數(shù)據(jù)庫的操作。如果出現(xiàn)了錯誤,我們撤銷之前的操作,就像玩一個雙關游戲一樣。

通過這種方法,我們能夠更加靈活地在方法中操作多個數(shù)據(jù)庫,而不用被注解的方式束縛。這種方式讓事務的控制更加精準,保證了數(shù)據(jù)的一致性。

1. 使用實例

首先看一下如何使用,下面的方法里有兩條sql,分別向兩個不同的數(shù)據(jù)庫插入數(shù)據(jù),我們在方法上加自定義注解`@MoreTransaction`,里面?zhèn)魅雰蓚€事務管理器的beann名稱,當有異常時,自定義注解的切面方法攔截到異常,兩條插入語句sql都會被回滾。
@MoreTransaction(value = {"transactionManagerOne","transactionManagerTwo"})
public ResultData getDataSourceList(){
  //向第一個數(shù)據(jù)庫插入數(shù)據(jù)
  int i=userService.addUser(new User().setUserName("數(shù)據(jù)庫1"));
  //故意制造異常,拋出給事務切面
  int a=1/0;
  //向第二個是數(shù)據(jù)庫插入數(shù)據(jù)
  int k=userService.addUserInfo(new UserInfo().setUserAccount("數(shù)據(jù)庫2"));
  Map map=new HashMap();
  map.put("k",k);
  return ResultData.success(map);
}

2. 首先分別配置兩個數(shù)據(jù)庫的數(shù)據(jù)源和事務管理器。

  • 定義第一個第一個數(shù)據(jù)源DataSourceOne,定義事務管理器的bean為 transactionManagerOne
/**
 * 數(shù)據(jù)源1
 */
@Configuration
@MapperScan(basePackages = "com.example.mybatis.mapper",sqlSessionFactoryRef = "sqlSessionFactoryOne")
public class DataSourceConfigOne {

    //配置第一個數(shù)據(jù)源的事務管理器,定義bean名稱為 transactionManagerOne
    @Bean(name = "transactionManagerOne")
    public PlatformTransactionManager transactionManagerOne(@Qualifier("dataSourceOne") DataSource dataSourceOne) {
        return new DataSourceTransactionManager(dataSourceOne);
    }

		//  --- 下面是配置數(shù)據(jù)源的代碼  --
  
  	@Bean(name = "dataSourceOne")
    @Primary// 表示這個數(shù)據(jù)源是默認數(shù)據(jù)源
    // 讀取application.properties中的配置參數(shù)映射成為一個對象,prefix表示參數(shù)的前綴
    @ConfigurationProperties(prefix = "spring.datasource.one")
    public DataSource dataSourceOne() {
        return  DataSourceBuilder.create().build();
    }
  
      @Primary
    public SqlSessionTemplate sqlsessiontemplateOne(@Qualifier("sqlsessiontemplateOne") SqlSessionFactory sessionfactory) {
        return new SqlSessionTemplate(sessionfactory);
    }

    @Bean(name = "sqlSessionFactoryOne")
    @Primary
    public SqlSessionFactory sqlSessionFactoryOne(@Qualifier("dataSourceOne") DataSource datasource)throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(datasource);
        bean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        return bean.getObject();
    }
}
  • 定義第一個第一個數(shù)據(jù)源DataSourceTwo,定義事務管理器的bean為 transactionManagerTwo
/**
 * 數(shù)據(jù)源2
 */
@Configuration
@MapperScan(basePackages = "com.example.mybatis.mapper2",sqlSessionFactoryRef = "sqlSessionFactoryTwo")
public class DataSourceConfigTwo {
  	//配置第一個數(shù)據(jù)源的事務管理器,定義bean名稱為 transactionManagerOne
  	@Bean(name = "transactionManagerTwo")
    public PlatformTransactionManager transactionManagerTwo(@Qualifier("dataSourceTwo") DataSource dataSourceTwo) {
        return new DataSourceTransactionManager(dataSourceTwo);
    }
  
  
  	//  --- 下面是配置數(shù)據(jù)源的代碼  --
    @Bean(name = "dataSourceTwo")
    @ConfigurationProperties(prefix = "spring.datasource.two")
    public DataSource dataSourceTwo() {
        return  DataSourceBuilder.create().build();
    }

    @Bean(name = "sqlSessionFactoryTwo")
    public SqlSessionFactory sqlSessionFactoryTwo(@Qualifier("dataSourceTwo") DataSource datasource)throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(datasource);
        bean.setMapperLocations(
                // 設置mybatis的xml所在位置
                new PathMatchingResourcePatternResolver().getResources("classpath:mapper2/*.xml"));
        bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);//下劃線-駝峰映射
        return bean.getObject();
    }
    

    public SqlSessionTemplate sqlsessiontemplateTwo(@Qualifier("sqlsessiontemplateTwo") SqlSessionFactory sessionfactory) {
        return new SqlSessionTemplate(sessionfactory);
    }
}

3. 使用自定義注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.PARAMETER})
public @interface MoreTransaction {
    String[] value() default {};
}

4. 事務切面方法,多數(shù)據(jù)源事務的實現(xiàn)(重點)

@Aspect
@Component
public class TransactionAop {
    @Pointcut("@annotation(com.example.mybatis.config.aop.annotation.MoreTransaction)")
    public void MoreTransaction() {
    }

    @Pointcut("execution(* com.example.mybatis.controller.*.*(..))")
    public void excudeController() {
    }

    @Around(value = "MoreTransaction()&&excudeController()&&@annotation(annotation)")
    public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint, MoreTransaction annotation) throws Throwable {
      	//存放事務管理器的棧
        Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack = new Stack<>();
      	//存放事務的狀態(tài),每一個DataSourceTransactionManager 對應一個 TransactionStatus
        Stack<TransactionStatus> transactionStatuStack = new Stack<>();

        try {
          	//判斷自定義注解@MoreTransaction 是否傳入事務管理器的名字,將自定義注解的值對應的事務管理器入棧
            if (!openTransaction(dataSourceTransactionManagerStack, transactionStatuStack, annotation)) {
                return null;
            }
          	//執(zhí)行業(yè)務方法
            Object ret = thisJoinPoint.proceed();
          	//如果沒有異常,說明兩個sql都執(zhí)行成功,兩個數(shù)據(jù)源的sql全部提交事務
            commit(dataSourceTransactionManagerStack, transactionStatuStack);
            return ret;
        } catch (Throwable e) {
          	//業(yè)務代碼發(fā)生異常,回滾兩個數(shù)據(jù)源的事務
            rollback(dataSourceTransactionManagerStack, transactionStatuStack);
            log.error(String.format("MultiTransactionalAspect, method:%s-%s occors error:",
                    thisJoinPoint.getTarget().getClass().getSimpleName(), thisJoinPoint.getSignature().getName()), e);
            throw e;
        }
    }

    /**
     * 開啟事務處理方法
     *
     * @param dataSourceTransactionManagerStack
     * @param transactionStatuStack
     * @param multiTransactional
     * @return
     */
    private boolean openTransaction(Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack,
                                    Stack<TransactionStatus> transactionStatuStack,MoreTransaction multiTransactional) {
				// 獲取需要開啟事務的事務管理器名字
        String[] transactionMangerNames = multiTransactional.value();
     	 // 檢查是否有需要開啟事務的事務管理器名字
        if (ArrayUtils.isEmpty(multiTransactional.value())) {
            return false;
        }
     	 // 遍歷事務管理器名字數(shù)組,逐個開啟事務并將事務狀態(tài)和管理器存入棧中
        for (String beanName : transactionMangerNames) {
         	 // 從Spring上下文中獲取事務管理器
            DataSourceTransactionManager dataSourceTransactionManager =(DataSourceTransactionManager) SpringContextUtil.getBean(beanName);
          	// 創(chuàng)建新的事務狀態(tài)
            TransactionStatus transactionStatus = dataSourceTransactionManager
                    .getTransaction(new DefaultTransactionDefinition());
         	 // 將事務狀態(tài)和事務管理器存入對應的棧中
            transactionStatuStack.push(transactionStatus);
            dataSourceTransactionManagerStack.push(dataSourceTransactionManager);
        }
        return true;
    }

    /**
     * 提交處理方法
     *
     * @param dataSourceTransactionManagerStack
     * @param transactionStatuStack
     */
    private void commit(Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack,
                        Stack<TransactionStatus> transactionStatuStack) {
      	// 循環(huán),直到事務管理器棧為空
        while (!dataSourceTransactionManagerStack.isEmpty()) {
          // 從事務管理器棧和事務狀態(tài)棧中分別彈出當前的事務管理器和事務狀態(tài)
          // 提交當前事務狀態(tài)
            dataSourceTransactionManagerStack.pop()
              .commit(transactionStatuStack.pop());
        }
    }

    /**
     * 回滾處理方法
     * @param dataSourceTransactionManagerStack
     * @param transactionStatuStack
     */
    private void rollback(Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack,
                          Stack<TransactionStatus> transactionStatuStack) {
     	 // 循環(huán),直到事務管理器棧為空
        while (!dataSourceTransactionManagerStack.isEmpty()) {
          // 從事務管理器棧和事務狀態(tài)棧中分別彈出當前的事務管理器和事務狀態(tài)
          // 回滾當前事務狀態(tài)
            dataSourceTransactionManagerStack.pop().rollback(transactionStatuStack.pop());
        }
    }
}

5. 使用事務注解,將兩個數(shù)據(jù)源的事務管理器名字作為參數(shù)傳入。

@MoreTransaction(value = {"transactionManagerOne","transactionManagerTwo"})
public ResultData getDataSourceList(){
  //向第一個數(shù)據(jù)庫插入數(shù)據(jù)
  int i=userService.addUser(new User().setUserName("數(shù)據(jù)庫1"));
  //故意制造異常,拋出給事務切面
  int a=1/0;
  //向第二個是數(shù)據(jù)庫插入數(shù)據(jù)
  int k=userService.addUserInfo(new UserInfo().setUserAccount("數(shù)據(jù)庫2"));
  Map map=new HashMap();
  map.put("k",k);
  return ResultData.success(map);
}

6. 提交請求后會發(fā)現(xiàn)控制臺報錯,但是數(shù)據(jù)庫里面并沒有插入數(shù)據(jù)。

多個數(shù)據(jù)源如何實現(xiàn)事務,spring,spring boot,mybatis,oracle,mysql,數(shù)據(jù)庫,sql,后端
多個數(shù)據(jù)源如何實現(xiàn)事務,spring,spring boot,mybatis,oracle,mysql,數(shù)據(jù)庫,sql,后端文章來源地址http://www.zghlxwxcb.cn/news/detail-790917.html

到了這里,關于解決多數(shù)據(jù)源的事務問題 - 基于springboot--mybatis的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【萬字長文】SpringBoot整合Atomikos實現(xiàn)多數(shù)據(jù)源分布式事務(提供Gitee源碼)

    前言:在最近的實際開發(fā)的過程中,遇到了在多數(shù)據(jù)源的情況下要保證原子性的問題,這個問題當時遇到了也是思考了一段時間,后來通過搜集大量資料與學習,最后是采用了分布式事務來解決這個問題,在講解之前,在我往期的博客提前搭好了一個SpringBoot整合MyBatis搭建M

    2024年02月14日
    瀏覽(26)
  • CompletableFuture異步編程事務及多數(shù)據(jù)源配置問題(含gitee源碼)

    CompletableFuture異步編程事務及多數(shù)據(jù)源配置問題(含gitee源碼)

    倉庫地址:?buxingzhe: 一個多數(shù)據(jù)源和多線程事務練習項目 小伙伴們在日常編碼中經(jīng)常為了提高程序運行效率采用多線程編程,在不涉及事務的情況下,使用dou.lea大神提供的CompletableFuture異步編程利器,它提供了許多優(yōu)雅的api,我們可以很方便的進行異步多線程編程,速度杠杠

    2024年02月05日
    瀏覽(19)
  • Springboot+mybatis-plus+dynamic-datasource+Druid 多數(shù)據(jù)源 分布式事務

    Springboot+mybatis-plus+dynamic-datasource+Druid 多數(shù)據(jù)源 分布式事務

    背景 處理多數(shù)據(jù)源事務一直是一個復雜而棘手的問題,通常我們有兩種主流的解決方法。 第一種是通過Atomikos手動創(chuàng)建多數(shù)據(jù)源事務,這種方法更適合數(shù)據(jù)源數(shù)量較少,參數(shù)配置不復雜,對性能要求不高的項目。然而,這種方法的最大困難在于需要手動配置大量設置,這可能

    2024年02月11日
    瀏覽(26)
  • [前車之鑒] SpringBoot原生使用Hikari數(shù)據(jù)連接池升級到動態(tài)多數(shù)據(jù)源的深坑解決方案 & RocketMQ吞掉異常問題排查

    [前車之鑒] SpringBoot原生使用Hikari數(shù)據(jù)連接池升級到動態(tài)多數(shù)據(jù)源的深坑解決方案 & RocketMQ吞掉異常問題排查

    當前業(yè)務場景我們使用原生SpringBoot整合Hikari數(shù)據(jù)源連接池提供服務,但是近期業(yè)務迭代需要使用動態(tài)多數(shù)據(jù)源,很自然想到dynamic-source,結果一系列慘案離奇發(fā)生。。。 原生SpringBoot整合HikariCp數(shù)據(jù)源連接池配置【這個是沒問題的配置】 而升級后的動態(tài)多數(shù)據(jù)源配置如下:【

    2024年02月01日
    瀏覽(32)
  • SpringBoot3整合Druid數(shù)據(jù)源的解決方案

    SpringBoot3整合Druid數(shù)據(jù)源的解決方案

    druid-spring-boot-3-starter目前最新版本是1.2.20,雖然適配了SpringBoot3,但缺少自動裝配的配置文件,會導致加載時報加載驅動異常。 需要手動在resources目錄下創(chuàng)建 META-INF/spring/ 目錄,并且在 META-INF/spring/ 創(chuàng)建 org.springframework.boot.autoconfigure.AutoConfiguration.imports , 文件中添加如下內容

    2024年03月09日
    瀏覽(39)
  • 基于注解切換、Hikari實現(xiàn)的SpringBoot動態(tài)數(shù)據(jù)源(支持JNDI)

    先說效果,要實現(xiàn)方法級別注解切換當前數(shù)據(jù)源,不設置注解時走默認數(shù)據(jù)源,同時支持JNDI源。 Spring框架中存在一個抽象類 AbstractRoutingDataSource ,他是一個可以動態(tài)選擇當前DataSource的路由類,我們就是要從這里入手,重新實現(xiàn)數(shù)據(jù)源的切換選擇邏輯。然后借助注解和切面,

    2024年02月08日
    瀏覽(33)
  • 解決WPF綁定數(shù)據(jù)源,數(shù)據(jù)更新,UI不更新的問題

    XAML中已經(jīng)設置 View中已經(jīng)實現(xiàn)IDisposable接口。 ViewModel中已經(jīng)實現(xiàn)INotifyPropertyChanged接口方法RaisePropertyChanged。 Model中已經(jīng)配置TextValue 如果已經(jīng)正確設置Model與ViewModel的 INotifyPropertyChanged ,且Model中的數(shù)據(jù)可以執(zhí)行 RaisePropertyChanged ,但此時UI仍不能更新,請檢查View中是否 DataCont

    2024年02月14日
    瀏覽(22)
  • 千云物流- 多數(shù)據(jù)源事務管理

    Spring只是個容器,因此它并不做任何事務的具體實現(xiàn)。他只是提供了事務管理的接口PlatformTransactionManager,具體內容由就由各個事務管理器來實現(xiàn)。 DataSourceTransactionManager:位于org.springframework.jdbc.datasource包中,數(shù)據(jù)源事務管理器,提供對單個javax.sql.DataSource事務管理,用于S

    2024年02月02日
    瀏覽(20)
  • SpringBoot+MyBatis-Plus多數(shù)據(jù)源@DS注解失效的解決方法

    引入 dynamic-datasource: application.yml 數(shù)據(jù)源配置: 詳細使用請看 MyBatis-Plus官網(wǎng) 這種場景還是比較常見,比如在一個為master數(shù)據(jù)源的調用slave數(shù)據(jù)源就會失效 slave數(shù)據(jù)源Service方法 mater數(shù)據(jù)源Service方法調用slave數(shù)據(jù)源Service方法 這里會出現(xiàn)沒有走slave_1,依然還是master數(shù)據(jù)源 需要在

    2024年01月18日
    瀏覽(28)
  • Spring Boot多數(shù)據(jù)源事務@DSTransactional的使用

    Spring Boot 集成com.baomidou,引入dynamic-datasource依賴,實現(xiàn)多數(shù)據(jù)源,這里說下事務問題: 1、一個方法中使用同一個數(shù)據(jù)源; 2、一個方法中使用了多個數(shù)據(jù)源; 這里把dao、service列出來 1、dao層 ? 2、service層? spring boot實現(xiàn)多數(shù)據(jù)源:Spring Boot集成Druid實現(xiàn)多數(shù)據(jù)源的兩種方式_濤

    2024年02月11日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包