Spring動態配置多數據源

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

簡介

基本信息

Spring配置多數據源的方式和具體使用過程。

Spring對於多數據源,以資料庫表為參照,大體上可以分成兩大類情況:

一是,表級上的跨資料庫。即,對於不同的資料庫卻有相同的表(表名和表結構完全相同)。

二是,非表級上的跨資料庫。即,多個數據源不存在相同的表。

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

實現

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

一、動態配置多數據源

1. 數據源的名稱常量類:

package com.frogking.datasource;

public class DataSourceConst {

public static final String Admin="Admin";

public static final String User = "User";

}

2. 建立一個獲得和設定上下文環境的類,主要負責改變上下文數據源的名稱: package com.frogking.datasource;

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,一般是返回字元串: package com.frogking.datasource;

publicclass DynamicDataSource extends AbstractRoutingDataSource {

@Override

protected Object determineCurrentLookupKey() {

// 在進行DAO操作前,通過上下文環境變數,獲得數據源的類型

return DataSourceContextHolder. getDataSourceType();

}

}

4. 編寫spring的配置檔案配置多個數據源

<!-- 數據源相同的內容 -->

<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="parentDataSource">

<property name="driverClassName">

<value>com.mysql.jdbc.Driver</value>

</property>

<property name="username">

<value>root</value>

</property>

<property name="password">

<value>1234</value>

</property>

</bean>

<!-- 以下配置各個數據源的特性 -->

<!-- 資料庫test -->

<bean parent="parentDataSource" id="adminDataSource">

<property name="url">

<value>jdbc:mysql://localhost:3306/test</value>

</property>

</bean>

<!-- 不同的資料庫test2 -->

<bean parent="parentDataSource" id="userDataSource">

<property name="url">

<value>jdbc:mysql://localhost:3306/test2</value>

</property>

</bean>

<!-- end 配置各個數據源的特性 -->

5. 編寫spring配置檔案配置多數據源映射關係

<bean class="com.frogking.datasource.DynamicDataSource" id="dataSource">

<property name="targetDataSources">

<map key-type="java.lang.String">

<entry value-ref=" adminDataSource " key="Admin"></entry>

<entry value-ref=" userDataSource " key="User"></entry>

</map>

</property>

<property name="defaultTargetDataSource" ref="adminDataSource" >

</property>

</bean>

在這個配置中第一個property屬性配置目標數據源,<map key-type="java.lang.String">中的key-type必須要和靜態鍵值對照類DataSourceConst中的值的類型相 同;<entry key="User" value-ref="userDataSource"/>中key的值必須要和靜態鍵值對照類中的值相同,如果有多個值,可以配置多個< entry>標籤。第二個property屬性配置默認的數據源。

6. 配置hibernate,和普通的hibernate、spring結合的配置一樣:

<!-- sessionFactory的配置 -->

<BEAN class=org.springframework.orm.hibernate3.LocalSessionFactoryBean id=sessionFactory>

<property name="dataSource">

<REF local="dataSource"> </REF>

</property>

<!-- 實體類資源映射 -->

<property name="mappingResources">

<LIST>

<VALUE>com/frogking/entity/User.hbm.xml </VALUE>

<VALUE>com/frogking/entity/Admin.hbm.xml</VALUE> </LIST>

</property>

<!-- 為sessionFactory 配置Hibernate屬性 -->

<property name="hibernateProperties">

<PROPS>

<PROP key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect

</PROP>

<PROP key="hibernate.show_sql">true</PROP> <PROP key="hibernate.connection.autocommit">false</PROP> <PROP key="hibernate.cache.use_query_cache">false</PROP> <PROP key="hibernate.max_fetch_depth">2</PROP> <PROP key="hibernate.bytecode.use_reflection_optimizer">true</PROP>

</PROPS>

</property>

</BEAN>

<!-- 為dao配置sessionFactory -->

<BEAN class="com.frogking.dao.LoginHibernateDao" id=loginDao>

<property name="sessionFactory">

<REF local="sessionFactory"> </REF>

</property>

</BEAN>

基於spring和ibatis的多數據源切換方案

基本介紹

在僅使用ibatis時,多數據源簡直就是夢魘,每多一個數據源就需要多一份sql-map-config配置檔案。

採用spring的AbstractRoutingDataSource就可以簡單的解決這個問題。

AbstractRoutingDataSource實現了javax.sql.DataSource接口,因此可以理解為一個虛擬的動態DataSource,在需要的時候根據上下文Context動態決定使用哪個數據源。

該方案的優勢

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

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

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

該方案的缺點

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

相關詞條

熱門詞條

聯絡我們