欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring實(shí)現(xiàn)動(dòng)態(tài)切換多數(shù)據(jù)源的解決方案

 更新時(shí)間:2017年01月17日 11:20:13   作者:nevergiveupzeng  
這篇文章主要給大家介紹了Spring實(shí)現(xiàn)動(dòng)態(tài)切換多數(shù)據(jù)源的解決方案,文中給出了詳細(xì)的介紹和示例代碼,相信對(duì)大家的理解和學(xué)習(xí)具有一定的參考借鑒價(jià)值,有需要的朋友可以參考學(xué)習(xí),下面來一起看看吧。

前言

Spring動(dòng)態(tài)配置多數(shù)據(jù)源,即在大型應(yīng)用中對(duì)數(shù)據(jù)進(jìn)行切分,并且采用多個(gè)數(shù)據(jù)庫(kù)實(shí)例進(jìn)行管理,這樣可以有效提高系統(tǒng)的水平伸縮性。而這樣的方案就會(huì)不同于常見的單一數(shù)據(jù)實(shí)例的方案,這就要程序在運(yùn)行時(shí)根據(jù)當(dāng)時(shí)的請(qǐng)求及系統(tǒng)狀態(tài)來動(dòng)態(tài)的決定將數(shù)據(jù)存儲(chǔ)在哪個(gè)數(shù)據(jù)庫(kù)實(shí)例中,以及從哪個(gè)數(shù)據(jù)庫(kù)提取數(shù)據(jù)。

Spring2.x以后的版本中采用Proxy模式,就是我們?cè)诜桨钢袑?shí)現(xiàn)一個(gè)虛擬的數(shù)據(jù)源,并且用它來封裝數(shù)據(jù)源選擇邏輯,這樣就可以有效地將數(shù)據(jù)源選擇邏輯從Client中分離出來。Client提供選擇所需的上下文(因?yàn)檫@是Client所知道的),由虛擬的DataSource根據(jù)Client提供的上下文來實(shí)現(xiàn)數(shù)據(jù)源的選擇。

實(shí)現(xiàn)

具體的實(shí)現(xiàn)就是,虛擬的DataSource僅需繼承AbstractRoutingDataSource實(shí)現(xiàn)determineCurrentLookupKey()在其中封裝數(shù)據(jù)源的選擇邏輯。

一、動(dòng)態(tài)配置多數(shù)據(jù)源

1. 數(shù)據(jù)源的名稱常量類:

/** 
 * 動(dòng)態(tài)配置多數(shù)據(jù)源 
 * 數(shù)據(jù)源的名稱常量類 
 * @author LONGHUI_LUO 
 * 
 */ 
public class DataSourceConst { 
 public static final String TEST="test"; 
 public static final String USER="User"; 
} 

2. 建立一個(gè)獲得和設(shè)置上下文環(huán)境的類,主要負(fù)責(zé)改變上下文數(shù)據(jù)源的名稱:

/** 
 * 獲得和設(shè)置上下文環(huán)境 主要負(fù)責(zé)改變上下文數(shù)據(jù)源的名稱 
 * 
 * @author LONGHUI_LUO 
 * 
 */ 
public class DataSourceContextHolder { 
 private static final ThreadLocal contextHolder = new ThreadLocal(); // 線程本地環(huán)境 
 
 // 設(shè)置數(shù)據(jù)源類型 
 public static void setDataSourceType(String dataSourceType) { 
  contextHolder.set(dataSourceType); 
 } 
 
 // 獲取數(shù)據(jù)源類型 
 public static String getDataSourceType() { 
  return (String) contextHolder.get(); 
 } 
 
 // 清除數(shù)據(jù)源類型 
 public static void clearDataSourceType() { 
  contextHolder.remove(); 
 } 
 
} 

3. 建立動(dòng)態(tài)數(shù)據(jù)源類,注意,這個(gè)類必須繼承AbstractRoutingDataSource,且實(shí)現(xiàn)方法determineCurrentLookupKey,該方法返回一個(gè)Object,一般是返回字符串:

/** 
 * 建立動(dòng)態(tài)數(shù)據(jù)源 
 * 
 * @author LONGHUI_LUO 
 * 
 */ 
public class DynamicDataSource extends AbstractRoutingDataSource { 
 
 protected Object determineCurrentLookupKey() { 
 // 在進(jìn)行DAO操作前,通過上下文環(huán)境變量,獲得數(shù)據(jù)源的類型 
 return DataSourceContextHolder.getDataSourceType(); 
 } 
 
} 

4. 編寫spring的配置文件配置多個(gè)數(shù)據(jù)源

  <!-- 數(shù)據(jù)源相同的內(nèi)容 --> 
<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以下配置各個(gè)數(shù)據(jù)源的特性 --> 
<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 配置各個(gè)數(shù)據(jù)源的特性 --> 

5. 編寫spring配置文件配置多數(shù)據(jù)源映射關(guān)系

<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> 

在這個(gè)配置中第一個(gè)property屬性配置目標(biāo)數(shù)據(jù)源,<map key-type="java.lang.String">中的key-type必須要和靜態(tài)鍵值對(duì)照類DataSourceConst中的值的類型相 同;<entry key="User" value-ref="userDataSource"/>中key的值必須要和靜態(tài)鍵值對(duì)照類中的值相同,如果有多個(gè)值,可以配置多個(gè)< entry>標(biāo)簽。第二個(gè)property屬性配置默認(rèn)的數(shù)據(jù)源。

動(dòng)態(tài)切換是數(shù)據(jù)源

DataSourceContextHolder.setDataSourceType(DataSourceConst.TEST); 

該方案的優(yōu)勢(shì)

首先,這個(gè)方案完全是在spring的框架下解決的,數(shù)據(jù)源依然配置在spring的配置文件中,sessionFactory依然去配置它的dataSource屬性,它甚至都不知道dataSource的改變。唯一不同的是在真正的dataSource與sessionFactory之間增加了一個(gè)MultiDataSource。

其次,實(shí)現(xiàn)簡(jiǎn)單,易于維護(hù)。這個(gè)方案雖然我說了這么多東西,其實(shí)都是分析,真正需要我們寫的代碼就只有MultiDataSource、SpObserver兩個(gè)類。MultiDataSource類真正要寫的只有getDataSource()getDataSource(sp)兩個(gè)方法,而SpObserver類更簡(jiǎn)單了。實(shí)現(xiàn)越簡(jiǎn)單,出錯(cuò)的可能就越小,維護(hù)性就越高。

最后,這個(gè)方案可以使單數(shù)據(jù)源與多數(shù)據(jù)源兼容。這個(gè)方案完全不影響B(tài)US和DAO的編寫。如果我們的項(xiàng)目在開始之初是單數(shù)據(jù)源的情況下開發(fā),隨著項(xiàng)目的進(jìn)行,需要變更為多數(shù)據(jù)源,則只需要修改spring配置,并少量修改MVC層以便在請(qǐng)求中寫入需要的數(shù)據(jù)源名,變更就完成了。如果我們的項(xiàng)目希望改回單數(shù)據(jù)源,則只需要簡(jiǎn)單修改配置文件。這樣,為我們的項(xiàng)目將增加更多的彈性。

該方案的缺點(diǎn)

沒有能夠解決多用戶訪問單例“sessionFactory”時(shí)共享“dataSource”變量,導(dǎo)致產(chǎn)生爭(zhēng)搶“dataSource”的結(jié)果,本質(zhì)類似于操作系統(tǒng)中的“生產(chǎn)者消費(fèi)者”問題。因此當(dāng)多用戶訪問時(shí),多數(shù)據(jù)源可能會(huì)導(dǎo)致系統(tǒng)性能下降的后果。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。

相關(guān)文章

最新評(píng)論