Spring整合多數(shù)據(jù)源實(shí)現(xiàn)動(dòng)態(tài)切換的實(shí)例講解
在實(shí)際項(xiàng)目中時(shí)常需要連接多個(gè)數(shù)據(jù)庫(kù),而且不同的業(yè)務(wù)需求在實(shí)現(xiàn)過(guò)程當(dāng)中往往需要訪問(wèn)不同的數(shù)據(jù)庫(kù)。
jdbc.properties配置文件,配置多個(gè)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配置文件中去,同時(shí)配置DynamicDataSource的targetDataSources(多數(shù)據(jù)源目標(biāo))屬性的Map映射,使用動(dòng)態(tài)數(shù)據(jù)源DynamicDataSource是繼承與AbstractRoutingDataSource,而AbstractRoutingDataSource又是繼承于org.springframework.jdbc.datasource.AbstractDataSource,AbstractDataSource實(shí)現(xiàn)了統(tǒng)一的DataSource接口,所以DynamicDataSource同樣可以當(dāng)一個(gè)DataSource使用:
<!-- 數(shù)據(jù)庫(kù)連接池配置 --> <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" /> <!-- 配置獲取連接等待超時(shí)的時(shí)間 --> <property name="maxWait" value="30000" /> <!-- 配置間隔多久才進(jìn)行一次檢測(cè),檢測(cè)需要關(guān)閉的空閑連接,單位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一個(gè)連接在池中最小生存的時(shí)間,單位是毫秒 --> <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> <!-- 動(dòng)態(tài)數(shù)據(jù)源 --> <bean id="dynamicDataSource" class="com.yahu.core.dao.DynamicDataSource"> <!-- 通過(guò)key-value的形式來(lái)關(guān)聯(lián)數(shù)據(jù)源 --> <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動(dòng)態(tài)數(shù)據(jù)源類,擴(kuò)展Spring的AbstractRoutingDataSource抽象類,實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源,AbstractRoutingDataSource中的抽象方法determineCurrentLookupKey是實(shí)現(xiàn)數(shù)據(jù)源的route的核心.這里對(duì)該方法進(jìn)行Override:
package com.yahu.core.dao; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /******************************************************************* * @describe : 建立動(dòng)態(tài)數(shù)據(jù)源類 必須繼承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; } }
獲得和設(shè)置上下文環(huán)境,為一線程安全的ThreadLocal:
package com.yahu.core.dao; /******************************************************************* * @describe : 獲得和設(shè)置上下文環(huán)境 ********************************************************************/ 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(); } }
動(dòng)態(tài)數(shù)據(jù)源的管理,如何選擇控制每個(gè)業(yè)務(wù)中需要的具體數(shù)據(jù)源,可以使用手動(dòng)控制,業(yè)務(wù)層通過(guò)加入以下代碼
CustomerContextHolder.setCustomerType(CustomerContextHolder.DATASOURCE);
即可實(shí)現(xiàn)動(dòng)態(tài)切換數(shù)據(jù)源,如果在service層有比較統(tǒng)一的規(guī)則的話,也可以使用aop設(shè)置數(shù)據(jù)源使用,這里一般都是一個(gè)service一個(gè)數(shù)據(jù)源,所以最好使用aop在service層執(zhí)行完之后統(tǒng)一調(diào)用
CustomerContextHolder.clearCustomerType();
清空數(shù)據(jù)源信息。
當(dāng)然,在上面配置里面有個(gè)參數(shù)defaultTargetDataSource為默認(rèn)數(shù)據(jù)源,就是不設(shè)置數(shù)據(jù)源的話,就是用這個(gè)數(shù)據(jù)源。
以上這篇Spring整合多數(shù)據(jù)源實(shí)現(xiàn)動(dòng)態(tài)切換的實(shí)例講解就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java實(shí)現(xiàn)將txt文件轉(zhuǎn)成xls文件的方法
今天小編就為大家分享一篇Java實(shí)現(xiàn)將txt文件轉(zhuǎn)成xls文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10使用Spring Initializr方式如何快速構(gòu)建Spring Boot項(xiàng)目
Spring lnitializr是一個(gè)Web應(yīng)用,它提供了一個(gè)基本的項(xiàng)目結(jié)構(gòu),能夠幫助我們快速構(gòu)建一個(gè)基礎(chǔ)的Spring Boot項(xiàng)目,本文分步驟講解如何使用Spring Initializr方式構(gòu)建Spring Boot項(xiàng)目,感興趣的朋友跟隨小編一起看看吧2023-08-08SpringBoot 請(qǐng)求參數(shù)忽略大小寫的實(shí)例
這篇文章主要介紹了SpringBoot 請(qǐng)求參數(shù)忽略大小寫的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01Mybatis-plus批量去重插入ON DUPLICATE key update使用方式
這篇文章主要介紹了Mybatis-plus批量去重插入ON DUPLICATE key update使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12SpringBoot使用Sa-Token實(shí)現(xiàn)賬號(hào)封禁、分類封禁、階梯封禁的示例代碼
本文主要介紹了SpringBoot使用Sa-Token實(shí)現(xiàn)賬號(hào)封禁、分類封禁、階梯封禁的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07