在實際項目中時常需要連接多個資料庫,而且不同的業務需求在實現過程當中往往需要訪問不同的資料庫。 jdbc.properties配置文件,配置多個dataSource spring-config.xml配置文件如下,將DynamicDataSource Bean加入到Spring的上下文xml配置文件 ...
在實際項目中時常需要連接多個資料庫,而且不同的業務需求在實現過程當中往往需要訪問不同的資料庫。
jdbc.properties配置文件,配置多個dataSource
##########################MySQL##################################### hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect connection.driver_class=com.mysql.jdbc.Driver connection.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8 connection.username=yahu connection.password=123456 ##########################Oracle##################################### connection1.driver_class=oracle.jdbc.driver.OracleDriver connection1.url=jdbc\:oracle\:thin\:@localhost\:1521/MEDB connection1.username=yahu connection1.password=123456 ##########################Sql Server2008##################################### connection2.driver_class=net.sourceforge.jtds.jdbc.Driver connection2.url=jdbc:jtds:sqlserver://localhost:1433;DatabaseName=test connection2.username=yahu connection2.password=123456
spring-config.xml配置文件如下,將DynamicDataSource Bean加入到Spring的上下文xml配置文件中去,同時配置DynamicDataSource的targetDataSources(多數據源目標)屬性的Map映射,使用動態數據源DynamicDataSource是繼承與AbstractRoutingDataSource,而AbstractRoutingDataSource又是繼承於org.springframework.jdbc.datasource.AbstractDataSource,AbstractDataSource實現了統一的DataSource介面,所以DynamicDataSource同樣可以當一個DataSource使用:
<!-- 資料庫連接池配置 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${connection.driver_class}" /> <property name="url" value="${connection.url}" /> <property name="username" value="${connection.username}" /> <property name="password" value="${connection.password}" /> <property name="initialSize" value="5" /> <property name="minIdle" value="1" /> <property name="maxActive" value="200" /> <!-- 配置獲取連接等待超時的時間 --> <property name="maxWait" value="30000" /> <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000" /> </bean> <!-- Oracle --> <bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${connection1.driver_class}" /> <property name="url" value="${connection1.url}" /> <property name="username" value="${connection1.username}" /> <property name="password" value="${connection1.password}" /> </bean> <!-- Sql server 2008 --> <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${connection2.driver_class}" /> <property name="url" value="${connection2.url}" /> <property name="username" value="${connection2.username}" /> <property name="password" value="${connection2.password}" /> </bean> <!-- 動態數據源 --> <bean id="dynamicDataSource" class="com.yahu.core.dao.DynamicDataSource"> <!-- 通過key-value的形式來關聯數據源 --> <property name="targetDataSources"> <map> <entry value-ref="dataSource" key="datasource" /> <entry value-ref="dataSource1" key="datasource1" /> <entry value-ref="dataSource2" key="datasource2" /> </map> </property> <property name="defaultTargetDataSource" ref="dataSource" /> </bean>
DynamicDataSource動態數據源類,擴展Spring的AbstractRoutingDataSource抽象類,實現動態數據源,AbstractRoutingDataSource中的抽象方法determineCurrentLookupKey是實現數據源的route的核心.這裡對該方法進行Override:
package com.yahu.core.dao; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /******************************************************************* * @describe : 建立動態數據源類 必須繼承AbstractRoutingDataSource ********************************************************************/ public class DynamicDataSource extends AbstractRoutingDataSource { //coverity 修改 //private Log log = LogFactory.getLog(getClass()); protected Object determineCurrentLookupKey() { String value = CustomerContextHolder.getCustomerType(); //log.info(value); return value; } }
獲得和設置上下文環境,為一線程安全的ThreadLocal:
package com.yahu.core.dao; /******************************************************************* * @describe : 獲得和設置上下文環境 ********************************************************************/ public class CustomerContextHolder { /** * mysql */ public static final String DATASOURCE = "datasource"; /** * oracle */ public static final String DATASOURCE_1 = "datasource1"; /** * sql server */ public static final String DATASOURCE_2 = "datasource2"; 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(); } }
動態數據源的管理,如何選擇控制每個業務中需要的具體數據源,可以使用手動控制,業務層通過加入以下代碼
CustomerContextHolder.setCustomerType(CustomerContextHolder.DATASOURCE);
即可實現動態切換數據源,如果在service層有比較統一的規則的話,也可以使用aop設置數據源使用,這裡一般都是一個service一個數據源,所以最好使用aop在service層執行完之後統一調用
CustomerContextHolder.clearCustomerType();
清空數據源信息。
當然,在上面配置裡面有個參數defaultTargetDataSource為預設數據源,就是不設置數據源的話,就是用這個數據源。