您好,登錄后才能下訂單哦!
使用Spring如何實現配置多個數據源?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
1.配置兩個不同的數據源,如下(由于項目使用的是druid數據庫連接,配置可以會復雜點比較):
<!-- 數據源配置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> <!-- 監控數據庫 --> <property name="proxyFilters"> <list> <ref bean="log-filter" /> </list> </property> </bean>
<!-- 數據源配置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> <!-- 監控數據庫 --> <property name="proxyFilters"> <list> <ref bean="log-filter" /> </list> </property> </bean>
2.定義一個類繼承AbstractRoutingDataSource實現determineCurrentLookupKey方法,該方法可以實現數據庫的動態切換,如下:
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }
3.定義一個可以設置當前線程的變量的工具類,用于設置對應的數據源名稱:
public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); /** * @Description: 設置數據源類型 * @param dataSourceType 數據庫類型 * @return void * @throws */ public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } /** * @Description: 獲取數據源類型 * @param * @return String * @throws */ public static String getDataSourceType() { return contextHolder.get(); } /** * @Description: 清除數據源類型 * @param * @return void * @throws */ public static void clearDataSourceType() { contextHolder.remove(); } }
然后在spring中配置,如下:
<!-- 編寫spring 配置文件的配置多數源映射關系 --> <bean class="com.sino.access.database.DynamicDataSource" id="dataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry value-ref="testDataSource1" key="<span >testDataSource1</span><span >"></entry></span> <entry value-ref="testDataSource2" key="testDataSource2"></entry> </map> </property> <property name="defaultTargetDataSource" ref="testDataSource1"> </property> </bean> </bean>
這樣配置兩個數據源對應的key分別為testDataSource1和testDataSource2,默認數據庫是testDataSource。
4.完成以上步驟后,如果沒有數據庫的事務管理,已經可以實現數據庫的動態切換了。但是如果涉及到數據庫的事務管理,需要在數據庫事務開啟切換數據庫,
否則數據庫的切換只能在下次數據庫操作時才生效。可以定義一個aop處理類在數據庫事務開啟之前切換數據庫,如下:
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.設置數據庫事務切面和切換數據庫切面執行的順序,如下:
<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屬性設置執行的順序,這樣實現了帶事務管理的spring數據庫動態切換。
看完上述內容,你們掌握使用Spring如何實現配置多個數據源的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。