1. 程式人生 > >spring 動態資料來源不起作用

spring 動態資料來源不起作用

背景

工程中有兩個service,serviceA對應資料來源A,serviceB對應資料來源B

在serviceA.methodA()中呼叫serviceB.mehtodB()方法,雖然切換資料來源aop正確執行了,
但是serviceB.methodB()方法執行時,仍然使用的serviceA的資料來源。

動態資料來源主要方法類

@Component("datasourceAdvice")
public class DatasourceAdvice implements MethodBeforeAdvice {

    static Logger logger =LoggerFactory.getLogger(DatasourceAdvice.class);

    @Override
public void before(Method method, Object[] args, Object target) throws Throwable { String packName = target.getClass().getPackage().getName(); boolean reportFlag = packName.contains("dataSource2"); if(reportFlag){ logger.info("切換到資料來源B"+packName); CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_B); }else
{ logger.info("切換到資料來源A"+packName); CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_A); } } }
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;


public class DynamicDataSource extends  AbstractRoutingDataSource{
@Override protected Object determineCurrentLookupKey() { return CustomerContextHolder.getCustomerType(); } }
public class CustomerContextHolder {

    public static final String DATA_SOURCE_A = "dataSourceOne";  
    public static final String DATA_SOURCE_B = "dataSourceTwo";  


    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  
    public static void setCustomerType(String customerType) {  
        contextHolder.set(customerType);  
    }  
    public static String getCustomerType() {  
        return contextHolder.get();  
    }  
    public static void clearCustomerType() {  
        contextHolder.remove();  
    }  
}

就是說,serviceA.methodA執行時,aop設定了資料來源A(setCustomerType),然後呼叫getCustomerType方法。
serviceB.methodB執行時,aop設定了資料來源B(setCustomerType),但是並沒有呼叫getCustomerType方法,這是為什麼?
按理說切換成了資料來源B,也應該呼叫getCustomerType才對。

分析

serviceA.methodA、serviceB.methodB方法,事務傳播屬性都是required
執行到serviceA.methodA時,由於當前沒有事務,所以會建立事務,因為是新事務,所以會獲取getDBType,然後get db connection。繼續執行,到了serviceB.methodB,切換到資料來源B,但是serviceB.methodB事務傳播屬性是required,並且當前已經有了A建立的事務,所以methodB與methodA使用同一個事務,所以,就不會再getDBType。至此我們分析出,這是事務傳播屬性搗的鬼。

我們再回頭來看,根據需求,methodA與methodB應該是獨立的事務,互不影響,並且操作不同資料來源。所以把methodB事務傳播屬性設定為requires_new就可以了。

結論

只有建立新事務時,才會獲取資料來源,get db connection