首頁 Java java教程 Spring實作動態切換多資料來源的解決方案

Spring實作動態切換多資料來源的解決方案

Jan 24, 2017 am 10:44 AM

前言

Spring動態配置多重資料來源,即在大型應用中對資料進行切分,並且採用多個資料庫執行個體進行管理,這樣可以有效提高系統的水平伸縮性。而這樣的方案就會不同於常見的單一資料實例的方案,這就要程式在運行時根據當時的請求及系統狀態來動態的決定將資料儲存在哪個資料庫實例中,以及從哪個資料庫提取資料。

Spring2.x以後的版本中採用Proxy模式,就是我們在方案中實作一個虛擬的資料來源,並且用它來封裝資料來源選擇邏輯,這樣就可以有效地將資料來源選擇邏輯從Client中分離出來。 Client提供選擇所需的上下文(因為這是Client所知道的),由虛擬的DataSource根據Client提供的上下文來實現資料來源的選擇。

實作

具體的實作就是,虛擬的DataSource只需繼承AbstractRoutingDataSource實作determineCurrentLookupKey()在其中封裝資料來源的選擇邏輯。

一、動態配置多重資料來源

1. 資料來源的名稱常數類別:

/**
 * 动态配置多数据源
 * 数据源的名称常量类
 * @author LONGHUI_LUO
 *
 */
public class DataSourceConst {
 public static final String TEST="test";
 public static final String USER="User";
}
登入後複製

   


2. 建立一個情境來源改變環境的資料來源的主要獲得和設定資料來源,主要獲得和設定上下文環境的一個類別:

/**
 * 获得和设置上下文环境 主要负责改变上下文数据源的名称
 *
 * @author LONGHUI_LUO
 *
 */
public class DataSourceContextHolder {
 private static final ThreadLocal contextHolder = new ThreadLocal(); // 线程本地环境
  
 // 设置数据源类型
 public static void setDataSourceType(String dataSourceType) {
  contextHolder.set(dataSourceType);
 }
  
 // 获取数据源类型
 public static String getDataSourceType() {
  return (String) contextHolder.get();
 }
  
 // 清除数据源类型
 public static void clearDataSourceType() {
  contextHolder.remove();
 }
  
}
登入後複製

   


3. 建立動態數據源類,注意,這個類必須繼承AbstractRoutingDataSource,且實現方法determineCurrentLookupKey,該方法返回一個Object,一般是返回字符串:

/**
 * 建立动态数据源
 *
 * @author LONGHUI_LUO
 *
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
  
 protected Object determineCurrentLookupKey() {
 // 在进行DAO操作前,通过上下文环境变量,获得数据源的类型
 return DataSourceContextHolder.getDataSourceType();
 }
  
}
登入後複製

   


4. 編寫spring的設定檔配置多個資料來源

  <!-- 数据源相同的内容 -->
<bean
  id="parentDataSource"
  class="org.apache.commons.dbcp.BasicDataSource"
  destroy-method="close">
  <property
   name="driverClassName"
   value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
  <property name="username" value="sa" />
  <property name="password" value="net2com" />
</bean>
<!-- start以下配置各个数据源的特性 -->
<bean parent="parentDataSource" id="testDataSource">
  <propertynamepropertyname="url" value="jdbc:sqlserver://localhost:1433;databaseName=test" />
</bean>
<bean parent="parentDataSource" id="UserDataSource">
   <property
   name="url"
   value="jdbc:sqlserver://localhost:1433;databaseName=User" />
</bean>
<!-- end 配置各个数据源的特性 -->
登入後複製

   


5. 寫spring設定檔設定多重資料來源對應關係

<bean class="com.xxxx.datasouce.DynamicDataSource" id="dataSource">
 <property name="targetDataSources">
  <map key-type="java.lang.String">
   <entry value-ref="testDataSource" key="test"></entry>
   <entry value-ref="UserDataSource" key="User"></entry>
  </map>
 </property>
 <property name="defaultTargetDataSource" ref="testDataSource" ></property>
</bean>
登入後複製
 目標資料來源,中的key-type必須要和靜態鍵值對照類別DataSourceConst中的值的類型相同;中key的值必須要和靜態鍵值對照類別中的值相同,如果有多個值,可以配置多個< entry>標籤。第二個property屬性配置預設的資料來源。

動態切換是資料來源

DataSourceContextHolder.setDataSourceType(DataSourceConst.TEST);
登入後複製

   

該方案的優點

首先,這個方案完全是在spring的框架下解決的,資料來源仍然配置在springsion的設定檔中仍然配置在springsion它的dataSource屬性,它甚至不知道dataSource的改變。唯一不同的是在真正的dataSource與sessionFactory之間增加了一個MultiDataSource。


其次,實現簡單,易於維護。這個方案雖然我說了這麼多東西,其實都是分析,真正需要我們寫的程式碼就只有MultiDataSource、SpObserver兩個類別。 MultiDataSource類別真正要寫的只有getDataSource()和getDataSource(sp)兩個方法,而SpObserver類別更簡單了。實現越簡單,出錯的可能越小,維護性就越高。

最後,這個方案可以讓單一資料來源與多重資料來源相容。這個方案完全不影響BUS和DAO的編寫。如果我們的專案在開始之初是單一資料來源的情況下開發,隨著專案的進行,需要變更為多資料來源,則只需要修改spring配置,並少量修改MVC層以便在請求中寫入所需的資料來源名,變更就完成了。如果我們的專案希望改回單一資料來源,則只需要簡單修改設定檔。這樣,為我們的專案將增加更多的彈性。

該方案的缺點

沒有能夠解決多用戶訪問單例“sessionFactory”時共享“dataSource”變量,導致產生爭搶“dataSource”的結果,本質類似於操作系統中的“生產者消費者”問題。因此當多用戶存取時,多資料來源可能會導致系統效能下降的後果。


總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或工作能帶來一定的幫助,如果有疑問大家可以留言交流。

更多Spring實現動態切換多資料來源的解決方案相關文章請關注PHP中文網!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

公司安全軟件導致應用無法運行?如何排查和解決? 公司安全軟件導致應用無法運行?如何排查和解決? Apr 19, 2025 pm 04:51 PM

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

如何優雅地獲取實體類變量名構建數據庫查詢條件? 如何優雅地獲取實體類變量名構建數據庫查詢條件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

如何使用MapStruct簡化系統對接中的字段映射問題? 如何使用MapStruct簡化系統對接中的字段映射問題? Apr 19, 2025 pm 06:21 PM

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

如何將姓名轉換為數字以實現排序並保持群組中的一致性? 如何將姓名轉換為數字以實現排序並保持群組中的一致性? Apr 19, 2025 pm 11:30 PM

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本啟動Spring...

使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名構建查詢條件? 使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名構建查詢條件? Apr 19, 2025 pm 09:51 PM

在使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名以構建查詢條件,是一個常見的難題。本文將針...

Java對像如何安全地轉換為數組? Java對像如何安全地轉換為數組? Apr 19, 2025 pm 11:33 PM

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? 電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? Apr 19, 2025 pm 11:27 PM

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

See all articles