SpringBoot + Mybatis 多數據源切換無法進行 寫數據庫 操作記錄


  使用注解 + AOP代理的方式對業務包方法的標記,配置繼承AbstractRoutingDataSource類實現對於數據源的切換.
測試時, 可以進行查詢,但不能進行更新插入等寫數據庫操作。
使用@order() 默認值為2147483647,對切換數據源的注解和開啟事務注解進行標注, 測試失敗。
應用啟動時使用了@EnableTransactionManagement() 開啟了事務管理。

  用AOP切換數據源,AOP的切點必須在事務開啟之前切換,否則無效,因為spring一旦使用事務獲取連接,
則會在事務開啟后獲取到連接,后面的都是放入當前線程中,即事務內所用的連接都是同一個,此時是無法改變的,
必須要在事務開啟前切換好數據源才能達到目的。

  解決方法:編寫事務配置類,配置事務管理器
PlatformTransactionManager定義相關業務接口和實現類新的事務傳播行為。
(傳播行為定義了被調用方法的事務邊界) REQUIRES_NEW(),配置自定義的事務攔截器,將服務接口及實現類配置進去。

  • PlatformTransactionManager
package org.springframework.transaction;

import org.springframework.lang.Nullable;

public interface PlatformTransactionManager {
    //事務狀態
    TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
    //提交事務
    void commit(TransactionStatus var1) throws TransactionException;
    //回滾事務
    void rollback(TransactionStatus var1) throws TransactionException;
}
 
        
  • 配置事務管理器
 
        
@Bean(CUSTOMIZE_TRANSACTION_INTERCEPTOR_NAME) public TransactionInterceptor customizeTransactionInterceptor(PlatformTransactionManager transactionManager) { NameMatchTransactionAttributeSource transactionAttributeSource = new NameMatchTransactionAttributeSource(); RuleBasedTransactionAttribute readOnly = this.readOnlyTransactionRule(); RuleBasedTransactionAttribute required = this.requiredTransactionRule(); // 默認的只讀事務配置
        for (String methodName : DEFAULT_READ_ONLY_METHOD_RULE_TRANSACTION_ATTRIBUTES) { transactionAttributeSource.addTransactionalMethod(methodName, readOnly); } // 默認的傳播事務配置
        for (String methodName : DEFAULT_REQUIRED_METHOD_RULE_TRANSACTION_ATTRIBUTES) { transactionAttributeSource.addTransactionalMethod(methodName, required); } // 定制的只讀事務配置
        for (String methodName : customizeReadOnlyMethodRuleTransactionAttributes) { transactionAttributeSource.addTransactionalMethod(methodName, readOnly); } // 定制的傳播事務配置
        for (String methodName : customizeRequiredMethodRuleTransactionAttributes) { transactionAttributeSource.addTransactionalMethod(methodName, required); } return new TransactionInterceptor(transactionManager, transactionAttributeSource); }
 
        

 

  • 配置攔截器
@Bean public BeanNameAutoProxyCreator customizeTransactionBeanNameAutoProxyCreator() { BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator(); // 設置定制的事務攔截器
 beanNameAutoProxyCreator.setInterceptorNames(CUSTOMIZE_TRANSACTION_INTERCEPTOR_NAME); // 默認
        for ( String defaultTransactionBeanNameSuffix : DEFAULT_TRANSACTION_BEAN_NAMES ) { beanNameAutoProxyCreator.setBeanNames( defaultTransactionBeanNameSuffix ); } // 定制
        for (String customizeTransactionBeanName : customizeTransactionBeanNames) { beanNameAutoProxyCreator.setBeanNames(customizeTransactionBeanName); } beanNameAutoProxyCreator.setProxyTargetClass(true); return beanNameAutoProxyCreator; }

 

  • 傳播行為

( 傳播行為定義了被調用方法的事務邊界 )

 

傳播行為       propagation                             意義                          
PROPAGATION_REQUIRED 方法必須運行在一個事務內,如果當前存在一個事務,那么該方法運行在這個事務中,否則,將創建一個新的事務。
REQUIRES_NEW 創建一個新的事務,如果存在當前事務的話,暫停(掛起)當前事務 。
SUPPORTS 支持當前事務,如果當前沒有事務,就以非事務方式執行。
NOT_SUPPORTED 不執行當前事務;總是執行非事務。
MANDATORY 支持當前事務;如果當前事務不存在則拋出一個異常。
NESTED 如果當前存在事務的話,執行一個嵌套的事務,不存在創建新的。
NEVER 不支持當前事務;如果存在當前事務則拋出一個異常



  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM