1.資料源配置:
jdbc_multiple.properties:
2.spring-mybatis.xml配置:
3.dbcontextholder類(作用是設定你目前的資料源)
4.使用方式:當你需要進行crud等資料庫操作的之前 設定你需要使用的資料源即可
例:
其實再進行項目開發的時候,一個項目有可能不止用到一個資料源,為了提高資料庫的水準伸縮性,需要對多個資料庫執行個體進行管理,需要配置多資料源。
1. 配置多個資料源
這裡以兩個c3p0資料庫連接配接池的資料源作為執行個體。在spring架構下使用c3p0的資料庫需要加入c3p0-0.9.1.2.jar(現在最新的)這個支援包。這裡以資料同步項目為例:
資料來源庫的連接配接池資料源配置:
<bean id="datasourcefrom" class="com.mchange.v2.c3p0.combopooleddatasource">
<property name="driverclass" value="${jdbc.driver}" />
<property name="jdbcurl" value="${jdbc.from.url}" />
<property name="user" value="${jdbc.from.username}" />
<property name="password" value="${jdbc.from.password}" />
<property name="autocommitonclose" value="true" />
<property name="checkouttimeout" value="${cpool.checkouttimeout}" />
<property name="initialpoolsize" value="${cpool.minpoolsize}" />
<property name="minpoolsize" value="${cpool.minpoolsize}" />
<property name="maxpoolsize" value="${cpool.maxpoolsize}" />
<property name="maxidletime" value="${cpool.maxidletime}" />
<property name="acquireincrement" value="${cpool.acquireincrement}" />
<property name="maxidletimeexcessconnections" value="${cpool.maxidletimeexcessconnections}" />
</bean>
資料插入庫的連接配接池資料源配置:
<bean id="datasourceto" class="com.mchange.v2.c3p0.combopooleddatasource">
<property name="jdbcurl" value="${jdbc.to.url}" />
<property name="user" value="${jdbc.to.username}" />
<property name="password" value="${jdbc.to.password}" />
注意:上面url,user,password等值是從classpath下的jdbc.properties中取得的。
通過spring擷取屬性檔案中的值,以供配置檔案使用:
<bean class="org.springframework.beans.factory.config.propertyplaceholderconfigurer">
<property name="locations" value="classpath:jdbc.properties" />
2. 擴充spring的abstractroutingdatasource抽象類,實作動态資料源。
abstractroutingdatasource中的抽象方法determinecurrentlookupkey是實作資料源的route的核心.這裡對該方法進行override。
public class dynamicdatasource extends abstractroutingdatasource{
@override
protected object determinecurrentlookupkey() {
return dbcontextholder.getdbtype();
}
}
上下文dbcontextholder為一線程安全的threadlocal,具體代碼如下:
public class dbcontextholder{
public static final string data_source_from = "datasourcefrom";
public static final string data_source_to = "datasourceto";
private static final threadlocal<string> contextholder = new threadlocal<string>();
public static void setdbtype(string dbtype) {
contextholder.set(dbtype);
public static string getdbtype() {
return contextholder.get();
public static void cleardbtype() {
contextholder.remove();
3.配置動态資料源
将dynamicdatasource bean加入到spring的上下文xml配置檔案中去,同時配置dynamicdatasource的targetdatasources(多資料源目标)屬性的map映射。
<bean id="dynamicdatasource" class="datasource.dynamicdatasource" >
<!-- 通過key-value的形式來關聯資料源 -->
<property name="targetdatasources">
<map>
<entry value-ref="datasourcefrom" key="datasourcefrom"></entry>
<entry value-ref="datasourceto" key="datasourceto"></entry>
</map>
</property>
<property name="defaulttargetdatasource" ref="datasourcefrom" />
</bean>
4.使用動态資料源
例子中dynamicdatasource是繼承與abstractroutingdatasource,而abstractroutingdatasource又是繼承于org.springframework.jdbc.datasource.abstractdatasource,abstractdatasource實作了統一的datasource接口,是以dynamicdatasource同樣可以當一個datasource使用。
在spring的jdbctemplate使用動态資料源的配置示例:
<!-- jdbctemplate使用動态資料源的配置 -->
<bean id="jdbctemplate" class="org.springframework.jdbc.core.jdbctemplate">
<property name="datasource">
<ref bean="dynamicdatasource" />
<!-- 對jdbctemplate的應用封裝類 -->
<bean id="sqlbasedao" class="com.whty.dao.basedaoimpl">
<property name="jdbctemplate">
<ref bean="jdbctemplate" />
<bean id="sessionfactory" class="org.springframework.orm.hibernate3.annotation.annotationsessionfactorybean">
<!-- 和普通的datasource用法一樣 -->
<property name="datasource" ref="dynamicdatasource" />
<property name="configlocations" value="classpath:hibernate.cfg.xml" />
<property name="hibernateproperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
5.事務管理
使用動态資料源的時候,可以看出和使用單資料源的時候相比,在使用配置上幾乎沒有差别,在進行性事務管理配置的時候也沒有差别:
使用spring的jdbctemplate的事務管理配置示例:
<bean id="transactionmanager" class="org.springframework.jdbc.datasource.datasourcetransactionmanager">
<bean id="sqlbasedaoproxy" class="org.springframework.transaction.interceptor.transactionproxyfactorybean">
<property name="transactionmanager" ref="transactionmanager" />
<property name="target" ref="sqlbasedao" />
<property name="transactionattributes">
<prop key="insert*">propagation_required</prop>
<prop key="*">propagation_required,readonly</prop>
</props>
使用hibernate時的事務管理配置示例:
<tx:annotation-driven transaction-manager="transactionmanager"/>
<bean id="transactionmanager" class="org.springframework.orm.hibernate3.hibernatetransactionmanager">
<property name="sessionfactory" ref="sessionfactory" />
6.動态資料源的管理控制
如何選擇控制每個業務中需要的具體資料源,可是使用手動控制:
applicationcontext context = new classpathxmlapplicationcontext("applicationcontext.xml");
basedao dao = (basedao) context.getbean("sqlbasedao", basedaoimpl.class);
try {
dbcontextholder.setcustomertype(dbcontextholder.data_source_from);
system.err.println(dao.select("select count(*) sum from test t ").get(0).get("sum"));
dbcontextholder.setcustomertype(dbcontextholder.data_source_to);
} catch (exception e) {
e.printstacktrace();
也可以采用aop的控制方式:
@aspect
public class dynamicdatasourceaspect {
@pointcut("execution (public service.impl..*.*(..))")
public void serviceexecution(){}
@before("serviceexecution()")
public void setdynamicdatasource(joinpoint jp) {
for(object o : jp.getargs()) {
//處理具體的邏輯 ,根據具體的境況customercontextholder.setcustomertype()選取datasource
}
7.總結
通過擴充spring的abstractroutingdatasource可以很好的實作多資料源的rout效果,而且對擴充更多的資料源有良好的伸縮性,隻要增加資料源和修改dynamicdatasource的targetdatasources屬性配置就好。在資料源選擇控制上,可以采用手動控制(業務邏輯并不多的時候),也可以很好的用aop的@aspect在service的入口加入一個切面@pointcut,在@before裡判斷joinpoint的類容標明特定的資料源。