前兩篇文章已經介紹了動態數據源的具體實現過程,在經過一段時間的使用後,發現了兩個比較嚴重的問題,在這裏進行補充說明。
事務執行失敗時沒有切回默認數據源
@Transactional
註解的方法意味着使用數據庫事務執行方法中的 sql 操作,默認情況下當方法拋出不受檢查異常時,事務會進行回滾,我所實現的動態數據源方案通過 AOP 和註解的方式切換數據源, @Transactional
方法執行前切換目標數據源,執行完成後切換回默認數據源。
但當方法拋出不受檢查異常時,AOP 方法無法執行到切回默認數據源的語句,因此在下次使用數據源時就會出錯,期望使用的是默認數據源,然而並不是。
解決方法是把切回默認數據源的語句放在 finally(try {} funally {}
) 塊中執行。
@Around(value = "@annotation(dataSource)")
public Object changeDataSource(ProceedingJoinPoint point, DataSource dataSource) throws Throwable {
DsKey dsKey = dataSource.dsKey();
if (!DynamicDataSource.contains(dsKey)) {
return null;
}
DynamicDataSource.setDataSourceKey(dsKey);
try {
return point.proceed();
} finally { // 兼顧事務回滾的情況
DynamicDataSource.clearDataSourceType(); // 恢復默認
}
}
@Transactional
註解的方法中使用多個數據源
此時事務只會對前一個數據源生效,這裏就涉及到分佈式事務的知識,詳細的分析之後再進行總結,
可先參考以下文章: