Spring配置多個數(shù)據(jù)源并實(shí)現(xiàn)動態(tài)切換示例
1.配置兩個不同的數(shù)據(jù)源,如下(由于項(xiàng)目使用的是druid數(shù)據(jù)庫連接,配置可以會復(fù)雜點(diǎn)比較):
<!-- 數(shù)據(jù)源配置1 -->
<bean id="testDataSource1" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${unity.db.jdbc.url}" />
<property name="username" value="${db.login.name}"></property>
<property name="password" value="${db.login.password}" />
<property name="filters" value="${db.filters}"></property>
<property name="maxActive" value="${db.pool.maxActive}"></property>
<property name="initialSize" value="${db.pool.initialSize}"></property>
<property name="minIdle" value="${db.pool.minIdle}"></property>
<property name="maxWait" value="${db.maxWait}"></property>
<property name="timeBetweenEvictionRunsMillis" value="${db.timeBetweenEvictionRunsMillis}"></property>
<property name="minEvictableIdleTimeMillis" value="${db.minEvictableIdleTimeMillis}"></property>
<property name="validationQuery" value="${db.validationQuery}"></property>
<property name="testWhileIdle" value="${db.testWhileIdle}"></property>
<property name="testOnBorrow" value="${db.testOnBorrow}"></property>
<property name="testOnReturn" value="${db.testOnReturn}"></property>
<property name="poolPreparedStatements" value="${db.poolPreparedStatements}"></property>
<property name="maxOpenPreparedStatements" value="${db.maxOpenPreparedStatements}"></property>
<!-- 監(jiān)控?cái)?shù)據(jù)庫 -->
<property name="proxyFilters">
<list>
<ref bean="log-filter" />
</list>
</property>
</bean>
<!-- 數(shù)據(jù)源配置2 -->
<bean id="testDataSource2" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${pub.db.jdbc.url}" />
<property name="username" value="${db.login.name}"></property>
<property name="password" value="${db.login.password}" />
<property name="filters" value="${db.filters}"></property>
<property name="maxActive" value="${db.pool.maxActive}"></property>
<property name="initialSize" value="${db.pool.initialSize}"></property>
<property name="minIdle" value="${db.pool.minIdle}"></property>
<property name="maxWait" value="${db.maxWait}"></property>
<property name="timeBetweenEvictionRunsMillis" value="${db.timeBetweenEvictionRunsMillis}"></property>
<property name="minEvictableIdleTimeMillis" value="${db.minEvictableIdleTimeMillis}"></property>
<property name="validationQuery" value="${db.validationQuery}"></property>
<property name="testWhileIdle" value="${db.testWhileIdle}"></property>
<property name="testOnBorrow" value="${db.testOnBorrow}"></property>
<property name="testOnReturn" value="${db.testOnReturn}"></property>
<property name="poolPreparedStatements" value="${db.poolPreparedStatements}"></property>
<property name="maxOpenPreparedStatements" value="${db.maxOpenPreparedStatements}"></property>
<!-- 監(jiān)控?cái)?shù)據(jù)庫 -->
<property name="proxyFilters">
<list>
<ref bean="log-filter" />
</list>
</property>
</bean>
2.定義一個類繼承AbstractRoutingDataSource實(shí)現(xiàn)determineCurrentLookupKey方法,該方法可以實(shí)現(xiàn)數(shù)據(jù)庫的動態(tài)切換,如下:
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSourceType();
}
}
3.定義一個可以設(shè)置當(dāng)前線程的變量的工具類,用于設(shè)置對應(yīng)的數(shù)據(jù)源名稱:
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
/**
* @Description: 設(shè)置數(shù)據(jù)源類型
* @param dataSourceType 數(shù)據(jù)庫類型
* @return void
* @throws
*/
public static void setDataSourceType(String dataSourceType) {
contextHolder.set(dataSourceType);
}
/**
* @Description: 獲取數(shù)據(jù)源類型
* @param
* @return String
* @throws
*/
public static String getDataSourceType() {
return contextHolder.get();
}
/**
* @Description: 清除數(shù)據(jù)源類型
* @param
* @return void
* @throws
*/
public static void clearDataSourceType() {
contextHolder.remove();
}
}
然后在spring中配置,如下:
<!-- 編寫spring 配置文件的配置多數(shù)源映射關(guān)系 -->
<bean class="com.sino.access.database.DynamicDataSource" id="dataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="testDataSource1" key="<span style="font-family: Arial, Helvetica, sans-serif;">testDataSource1</span><span style="font-family: Arial, Helvetica, sans-serif;">"></entry></span>
<entry value-ref="testDataSource2" key="testDataSource2"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="testDataSource1">
</property>
</bean>
</bean>
這樣配置兩個數(shù)據(jù)源對應(yīng)的key分別為testDataSource1和testDataSource2,默認(rèn)數(shù)據(jù)庫是testDataSource。
4.完成以上步驟后,如果沒有數(shù)據(jù)庫的事務(wù)管理,已經(jīng)可以實(shí)現(xiàn)數(shù)據(jù)庫的動態(tài)切換了。但是如果涉及到數(shù)據(jù)庫的事務(wù)管理,需要在數(shù)據(jù)庫事務(wù)開啟切換數(shù)據(jù)庫,
否則數(shù)據(jù)庫的切換只能在下次數(shù)據(jù)庫操作時才生效??梢远x一個aop處理類在數(shù)據(jù)庫事務(wù)開啟之前切換數(shù)據(jù)庫,如下:
public class DataSourceAspect implements MethodBeforeAdvice,AfterReturningAdvice
{
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
// TODO Auto-generated method stub
DataSourceContextHolder.clearDataSourceType();
}
@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
if (method.isAnnotationPresent(DataSource.class))
{
DataSource datasource = method.getAnnotation(DataSource.class);
DataSourceContextHolder.setDataSourceType(datasource.name());
}
else
{
DataSourceContextHolder.setDataSourceType(SinoConstant.DataSourceType.unityDataSource.toString());
}
}
}
5.設(shè)置數(shù)據(jù)庫事務(wù)切面和切換數(shù)據(jù)庫切面執(zhí)行的順序,如下:
<aop:config>
<aop:pointcut id="transactionPointCut" expression="execution(* com.test.service.*.*(..))" />
<aop:advisor pointcut-ref="transactionPointCut"
advice-ref="txAdvice" order="2" />
<aop:advisor advice-ref="dataSourceExchange" pointcut-ref="transactionPointCut" order="1"/>
</aop:config>
利用aop的order屬性設(shè)置執(zhí)行的順序,這樣實(shí)現(xiàn)了帶事務(wù)管理的spring數(shù)據(jù)庫動態(tài)切換。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
web容器中實(shí)例化spring相關(guān)配置解析
這篇文章主要介紹了web容器中實(shí)例化spring相關(guān)配置解析,具有一定借鑒價值,需要的朋友可以參考下2018-01-01
Java8方法引用及構(gòu)造方法引用原理實(shí)例解析
這篇文章主要介紹了Java8方法引用及構(gòu)造方法引用原理實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09
SpringCloud分布式事務(wù)Seata部署和集成過程
這篇文章主要介紹了SpringCloud分布式事務(wù)Seata部署和集成過程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-10-10
特殊數(shù)據(jù)結(jié)構(gòu)之使用Java實(shí)現(xiàn)單調(diào)棧示例
這篇文章主要為大家介紹了特殊數(shù)據(jù)結(jié)構(gòu)之使用Java實(shí)現(xiàn)單調(diào)棧示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
使用feign服務(wù)調(diào)用添加Header參數(shù)
這篇文章主要介紹了使用feign服務(wù)調(diào)用添加Header參數(shù)的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
spring boot實(shí)戰(zhàn)之使用JSP的示例
本篇文章主要介紹了spring boot實(shí)戰(zhàn)之使用JSP的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10
解決SpringBoot啟動過后不能訪問jsp頁面的問題(超詳細(xì))
這篇文章主要介紹了解決SpringBoot啟動過后不能訪問jsp頁面的問題,文中通過示例代碼介紹的非常詳細(xì),有需要的朋友可以參考一下,希望對你有所幫助。2020-05-05
Spring Boot + Thymeleaf + Activiti 快速開發(fā)平臺項(xiàng)目 附源碼
這篇文章主要介紹了Spring Boot + Thymeleaf + Activiti 快速開發(fā)平臺項(xiàng)目附源碼,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04

