您好,登錄后才能下訂單哦!
這篇文章主要介紹了SpringMVC Mybatis配置多個數(shù)據(jù)源并切換代碼詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
最近公司一個項目需要連接兩個數(shù)據(jù)庫(A和B)操作,有的模塊查詢A庫,有的模塊查詢B庫,因此需要改造下,項目后臺用的是SpringMVC+Mybatis+MySQL架構(gòu),折騰了兩天后終于搞定了,在這里記錄過改造過程。
使用場景
多數(shù)據(jù)源的使用的場景一般有:
實現(xiàn)原理
Spring2.x的版本中采用Proxy模式,就是在方案中實現(xiàn)一個虛擬的數(shù)據(jù)源,并且用它來封裝數(shù)據(jù)源選擇邏輯,這樣就可以有效地將數(shù)據(jù)源選擇邏輯從Client中分離出來。Client提供選擇所需的上下文,由虛擬的DynamicDataSource根據(jù)Client提供的上下文來實現(xiàn)數(shù)據(jù)源的選擇。
具體的實現(xiàn)是虛擬的DynamicDataSource僅需繼承AbstractRoutingDataSource實現(xiàn)determineCurrentLookupKey(),該方法返回需要使用的DataSource的key值,然后根據(jù)這個key從resolvedDataSources這個map里取出對應(yīng)的DataSource,如果找不到則用默認的resolvedDefaultDataSource。
詳細實現(xiàn)過程
修改spring的配置文件
配置文件里需要配置多個數(shù)據(jù)源,改造后主要配置如下:
<bean id="dataSourceTargetA" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" scope="singleton"> <property name="driverClass" value="${jdbc.a.driverClassName}" /> <property name="jdbcUrl" value="${jdbc.a.url}" /> <property name="user" value="${jdbc.a.username}" /> <property name="password" value="${jdbc.a.password}" /> <!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數(shù)。Default: 3 --> <property name="acquireIncrement" value="${c3p0.acquireIncrement}"></property> <!--初始化時獲取三個連接,取值應(yīng)在minPoolSize與maxPoolSize之間。Default: 3 --> <property name="initialPoolSize" value="${c3p0.initialPoolSize}"></property> <!--最大空閑時間,60秒內(nèi)未使用則連接被丟棄。若為0則永不丟棄。Default: 0 --> <property name="maxIdleTime" value="${c3p0.maxIdleTime}"></property> <!--連接池中保留的最大連接數(shù)。Default: 15 --> <property name="maxPoolSize" value="${c3p0.maxPoolSize}"></property> <property name="minPoolSize" value="${c3p0.minPoolSize}"></property> <!--兩次連接中間隔時間,單位毫秒。Default: 1000 --> <property name="acquireRetryDelay" value="1000"></property> <!--定義在從數(shù)據(jù)庫獲取新連接失敗后重復嘗試的次數(shù)。Default: 30 --> <property name="acquireRetryAttempts" value="60"></property> <!--獲取連接失敗將會引起所有等待連接池來獲取連接的線程拋出異常。但是數(shù)據(jù)源仍有效保留,并在下次調(diào)用getConnection()的時候繼續(xù)嘗試獲取連接。如果設(shè)為true,那么在嘗試獲取連接失敗后該數(shù)據(jù)源將申明已斷開并永久關(guān)閉。Default: false --> <property name="breakAfterAcquireFailure" value="false"></property> </bean> <bean id="dataSourceTargetB" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" scope="singleton"> <property name="driverClass" value="${jdbc.b.driverClassName}" /> <property name="jdbcUrl" value="${jdbc.b.url}" /> <property name="user" value="${jdbc.b.username}" /> <property name="password" value="${jdbc.b.password}" /> <!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數(shù)。Default: 3 --> <property name="acquireIncrement" value="${c3p0.acquireIncrement}"></property> <!--初始化時獲取三個連接,取值應(yīng)在minPoolSize與maxPoolSize之間。Default: 3 --> <property name="initialPoolSize" value="${c3p0.initialPoolSize}"></property> <!--最大空閑時間,60秒內(nèi)未使用則連接被丟棄。若為0則永不丟棄。Default: 0 --> <property name="maxIdleTime" value="${c3p0.maxIdleTime}"></property> <!--連接池中保留的最大連接數(shù)。Default: 15 --> <property name="maxPoolSize" value="${c3p0.maxPoolSize}"></property> <property name="minPoolSize" value="${c3p0.minPoolSize}"></property> <!--兩次連接中間隔時間,單位毫秒。Default: 1000 --> <property name="acquireRetryDelay" value="1000"></property> <!--定義在從數(shù)據(jù)庫獲取新連接失敗后重復嘗試的次數(shù)。Default: 30 --> <property name="acquireRetryAttempts" value="60"></property> <!--獲取連接失敗將會引起所有等待連接池來獲取連接的線程拋出異常。但是數(shù)據(jù)源仍有效保留,并在下次調(diào)用getConnection()的時候繼續(xù)嘗試獲取連接。如果設(shè)為true,那么在嘗試獲取連接失敗后該數(shù)據(jù)源將申明已斷開并永久關(guān)閉。Default: false --> <property name="breakAfterAcquireFailure" value="false"></property> </bean> <!-- 動態(tài)數(shù)據(jù)源 --> <bean id="dynamicDataSource" class="com.test.util.DynamicDataSource" > <property name="targetDataSources"> <map key-type="java.lang.String"> <entry value-ref="dataSourceTargetA" key="dataSourceTargetA"></entry> <entry value-ref="dataSourceTargetB" key="dataSourceTargetB"></entry> </map> </property> <property name="defaultTargetDataSource" ref="dataSourceTargetA" > </property> </bean> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dynamicDataSource" /> </bean> <!-- MyBatis ORM operation class --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dynamicDataSource" /> <property name="mapperLocations"> <list> <value>classpath*:com/test/**/*Mapper.xml</value> </list> </property> <property name="configLocation" value="classpath:provider-sql-map-config.xml" /> </bean>
添加動態(tài)數(shù)據(jù)源管理類
DynamicDataSource類繼承AbstractRoutingDataSource,實現(xiàn)determineCurrentLookupKey()方法。
package com.test.util; import com.test.util.CustomerContextHolder; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /** * 動態(tài)數(shù)據(jù)源管理類 * */ public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return CustomerContextHolder.getCustomerType(); } }
數(shù)據(jù)源切換類
CustomerContextHolder類可以實現(xiàn)數(shù)據(jù)源A和B的切換,數(shù)據(jù)源標識保存在線程變量中,避免多線程操作數(shù)據(jù)源時互相干擾
package com.test.util; /** * 數(shù)據(jù)源切換類 * */ public class CustomerContextHolder { public static final String DATA_SOURCE_DEFAULT = "dataSourceTargetA"; public static final String DATA_SOURCE_B = "dataSourceTargetB"; private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setCustomerType(String customerType) { contextHolder.set(customerType); } public static String getCustomerType() { return contextHolder.get(); } public static void clearCustomerType() { contextHolder.remove(); } }
使用多數(shù)據(jù)源代碼
下面是Controller層代碼,需要查詢B數(shù)據(jù)源,查詢完成后切換為默認數(shù)據(jù)源A,具體代碼如下:
/** * 訂單列表查詢,查詢B數(shù)據(jù)源 * * @param request * @return */ @RequestMapping(value = "/list") public String list(HttpServletRequest request, Integer cId) { //設(shè)置數(shù)據(jù)源B CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_B); List<Order> orderList = salaryBillService.getSalaryOrderByOrgId(cId); request.setAttribute("orderList", orderList); //切換回默認數(shù)據(jù)源A CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_DEFAULT); return "/jsp/order"; }
上述四步操作完成后即可實現(xiàn)SpringMVC+Mybatis配置多個數(shù)據(jù)源并切換,有問題歡迎留言溝通哦!
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。