mybatis 多資料來源動態切換
阿新 • • 發佈:2020-11-21
>筆者主要從事c#開發,近期因為專案需要,搭建了一套spring-cloud微服務框架,集成了eureka服務註冊中心、
gateway閘道器過濾、admin服務監控、auth授權體系驗證,集成了redis、swagger、jwt、mybatis多資料來源等各項功能。
具體搭建過程後續另寫播客介紹。具體結構如下:
![](https://img2020.cnblogs.com/blog/1056199/202011/1056199-20201121105816810-85639865.png)
>在搭建過程整合mybatis的時候,考慮到單一資料來源無法滿足實際業務需要,故結合c#的開發經驗,進行多資料來源動態整合。
mybatis的多資料來源可以採用兩種方式進行,第一種是分包方式實現,這種方式靈活性不高,而且較為繁瑣,故不做過多介紹。
另一種方式是採用AOP的思想,進行註解動態切換,參考網上教程,核心思想是依靠 繼承AbstractRoutingDataSource,
重寫determineCurrentLookupKey()方法,在該方法中使用DatabaseContextHolder獲取當前執行緒的dataSource。
但是網上方法大都是首先定義好各個datasource,比如有三個資料來源,就需要實現定義好三個datasource,筆者感覺這種方法,在我
目前這套框架中不夠靈活,因為筆者採用的是微服務框架,考慮到各個服務都有可能使用不同的資料來源,而多資料來源動態切換
是放在公共方法中實現的,如果每有新的資料來源就要定義一個,對程式碼的侵入性太高,在c#中,選擇資料來源很容易,根據連線名
稱就可以切換過去,
如下所示:
```
```
能不能像c#這樣根據連線名稱就自動選擇呢,筆者的連線配置如下所示:
```
spring:
application:
name: csg-auth
datasource:
kbase:
- driverClassName: com.kbase.jdbc.Driver
jdbcUrl: jdbc:kbase://127.0.0.1
username: DBOWN
password:
jdbc:
- driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://localhost:3306/nacos?serverTimezone=GMT%2B8&useUnicode=false&characterEncoding=utf8&useSSL=false
username: root
password: 123456
connName: nacos
- driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://localhost:3306/tpi?serverTimezone=GMT%2B8&useUnicode=false&characterEncoding=utf8&useSSL=false
username: root
password: 123456
connName: tpi
```
其中kbase不用理會,是我們公司自己的資料庫,jdbc是維護的連線集合,其中connName就是我們自定義的連線名稱,
根據connName就可以自動切換到對應資料來源。
> 筆者實現程式碼如下:
![](https://img2020.cnblogs.com/blog/1056199/202011/1056199-20201121111913575-1546678626.png)
### 第一步
>首先,編寫DynamicDataSource類整合AbstractRoutingDataSource,重寫determineCurrentLookupKey方法,該方法主要作用是選擇資料來源的key
程式碼如下:
```
/**
* 動態資料來源
* */
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceHolder.getDataSource();
}
}
```
### 第二步
>第二部編寫DataSourceHolder類,提供設定、獲取、情況資料來源的方法,如下所示:
```
public class DataSourceHolder {
/**
* 執行緒本地環境
*/
private static final ThreadLocal dataSources = new ThreadLocal();
/**
* 設定資料來源
*/
public static void setDataSources(String connName) {
dataSources.set(connName);
}
/**
* 獲取資料來源
*/
public static String getDataSource() {
return dataSources.get();
}
/**
* 清楚資料來源
*/
public static void clearDataSource() {
dataSources.remove();
}
}
```
### 第三步
>第三步,編寫DataSourceConfig類,該類主要作用是讀取配置檔案中的資料來源連線集合,以及維護專案資料來源的Bean物件,
程式碼如下:
```
@Component
@ConfigurationProperties("spring.datasource")
public class DataSourceConfig {
private List jdbc;
public Map