【教程】Spring+Mybatis環境配置多資料來源
一、簡要概述
在做專案的時候遇到需要從兩個資料來源獲取資料,專案使用的Spring + Mybatis環境,看到網上有一些關於多資料來源的配置,自己也整理學習一下,然後自動切換實現從不同的資料來源獲取資料功能。
二、程式碼詳解
2.1 DataSourceConstants
資料來源常量類
/**
* 資料來源名稱常量類
* 對應 application.xml 中 bean multipleDataSource
* @author:dufy
* @version:1.0.0
* @date 2018/12/17
*/
public class DataSourceConstants {
/**
* 資料來源1,預設資料來源配置
*/
public static final String DATASOURCE_1 = "dataSource1";
/**
* 資料來源2
*/
public static final String DATASOURCE_2 = "dataSource2";
}
2.2 DataSourceType
自定義資料來源註解
/**
* 自定義資料來源型別註解
*
* @author:dufy
* @version:1.0.0
* @date 2018/12/17
*/
@Target (ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSourceType {
String value() default DataSourceConstants.DATASOURCE_1;
}
2.3 MultipleDataSource
多資料來源配置類
MultipleDataSource
繼承 AbstractRoutingDataSource
類,為什麼繼承這個類就可以了?請看 第五章 :實現原理。
import org.springframework. jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 自定義多資料來源配置類
*
* @author:dufy
* @version:1.0.0
* @date 2018/12/17
*/
public class MultipleDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> dataSourceHolder = new ThreadLocal<String>();
/**
* 設定資料來源
* @param dataSource 資料來源名稱
*/
public static void setDataSource(String dataSource){
dataSourceHolder.set(dataSource);
}
/**
* 獲取資料來源
* @return
*/
public static String getDatasource() {
return dataSourceHolder.get();
}
/**
* 清除資料來源
*/
public static void clearDataSource(){
dataSourceHolder.remove();
}
@Override
protected Object determineCurrentLookupKey() {
return dataSourceHolder.get();
}
}
2.4 MultipleDataSourceAop
多資料來源自動切換通知類
注意:請設定 @Order(0)。否則可能出現 資料來源切換失敗問題! 因為要在事務開啟之前就進行判斷,並進行切換資料來源!
/**
* 多資料來源自動切換通知類<br>
* <p>
* 首先判斷當前類是否被該DataSourceType註解進行註釋,如果沒有指定註解,則採用預設的資料來源配置; <br>
* 如果有,則讀取註解中的value值,將資料來源切到value指定的資料來源
*
* @author:dufy
* @version:1.0.0
* @date 2018/12/17
*/
@Aspect // for aop
@Component // for auto scan
@Order(0) // execute before @Transactional
public class MultipleDataSourceAop {
private final Logger logger = Logger.getLogger(MultipleDataSourceAop.class);
/**
* 攔截 com.**.servicee中所有的方法,根據配置情況進行資料來源切換
* com.jiuling.tz.service
* com.jiuling.web.service
* @param joinPoint
* @throws Throwable
*/
@Before("execution(* com.dufy.*.service.*.*(..))")
public void changeDataSource(JoinPoint joinPoint) throws Throwable {
try {
// 攔截的實體類,就是當前正在執行的service
Class<?> clazz = joinPoint.getTarget().getClass();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 提取目標物件方法註解和型別註解中的資料來源標識
Class<?>[] types = method.getParameterTypes();
if (clazz.isAnnotationPresent(DataSourceType.class)) {
DataSourceType source = clazz.getAnnotation(DataSourceType.class);
MultipleDataSource.setDataSource(source.value());
logger.info("Service Class 資料來源切換至--->" + source.value());
}
Method m = clazz.getMethod(method.getName(), types);
if (m != null && m.isAnnotationPresent(DataSourceType.class)) {
DataSourceType source = m.getAnnotation(DataSourceType.class);
MultipleDataSource.setDataSource(source.value());
logger.info("Service Method 資料來源切換至--->" + source.value());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 方法結束後
*/
@After("execution(* com.dufy.*.service.*.*(..))")
public void afterReturning() throws Throwable {
try {
MultipleDataSource.clearDataSource();
logger.debug("資料來源已移除!");
} catch (Exception e) {
e.printStackTrace();
logger.debug("資料來源移除報錯!");
}
}
}
三、配置詳情
在 applicationContext.xml
中配置詳情
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 自動掃描包 ,將帶有註解的類 納入spring容器管理 -->
<context:component-scan base-package="com.dufy"></context:component-scan>
<!-- 引入配置檔案 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:jdbc.properties</value>
</list>
</property>
</bean>
<!-- dataSource1 配置 -->
<bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本屬性 url、user、password -->
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${ds.initialSize}"/>
<property name="minIdle" value="${ds.minIdle}"/>
<property name="maxActive" value="${ds.maxActive}"/>
<!-- 配置獲取連線等待超時的時間 -->
<property name="maxWait" value="${ds.maxWait}"/>
<!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="${ds.timeBetweenEvictionRunsMillis}"/>
<!-- 配置一個連線在池中最小生存的時間,單位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="${ds.minEvictableIdleTimeMillis}"/>
<property name="validationQuery" value="SELECT 'x'"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
<!-- 開啟PSCache,並且指定每個連線上PSCache的大小 -->
<property name="poolPreparedStatements" value="false"/>
<property name="maxPoolPreparedStatementPerConnectionSize" value="20"/>
<!-- 配置監控統計攔截的filters -->
<property name="filters" value="stat"/>
</bean>
<!-- dataSource2 配置-->
<bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本屬性 url、user、password -->
<property name="url" value="${jd.jdbc.url}"/>
<property name="username" value="${jd.jdbc.username}"/>
<property name="password" value="${jd.jdbc.password}"/>
<!-- 其他配置省略 -->
</bean>
<!--多資料來源配置-->
<bean id="multipleDataSource" class="com.jiuling.core.ds.MultipleDataSource">
<property name="defaultTargetDataSource" ref="dataSource1" />
<property name="targetDataSources">
<map key-type = "java.lang.String">
<entry key="dataSource1" value-ref="dataSource1"/>
<entry key="dataSource2" value-ref="dataSource2"/>
<!-- 這裡還可以加多個dataSource -->
</map>
</property>
</bean>
<!-- mybatis檔案配置,掃描所有mapper檔案 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" p:dataSource-ref="multipleDataSource"
p:configLocation="classpath:mybatis-config.xml"
p:mapperLocations="classpath:com/dufy/*/dao/*.xml"/>
<!-- spring與mybatis整合配置,掃描所有dao -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" p:basePackage="com.dufy.*.dao"
p:sqlSessionFactoryBeanName="sqlSessionFactory"/>
<!-- 對dataSource 資料來源進行事務管理 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="multipleDataSource"/>
<!-- 事務管理 通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 對insert,update,delete 開頭的方法進行事務管理,只要有異常就回滾 -->
<tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
<tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
<tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
<!-- select,count開頭的方法,開啟只讀,提高資料庫訪問效能 -->
<tx:method name="select*" read-only="true"/>
<tx:method name="count*" read-only="true"/>
<!-- 對其他方法 使用預設的事務管理 -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- 事務 aop 配置 -->
<aop:config>
<aop:pointcut id="serviceMethods" expression="execution(* com.dufy.*.service..*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>
<!-- 配置使Spring採用CGLIB代理 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 啟用對事務註解的支援 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
jdbc.properties
配置內容
##-------------mysql資料庫連線配置 ---------------------###
# dataSource1
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.1.110:3306/jdsc?useUnicode=true&characterEncoding=utf-8
jdbc.username=test
jdbc.password=123456
#配置初始化大小、最小、最大
ds.initialSize=1
ds.minIdle=1
ds.maxActive=20
#配置獲取連線等待超時的時間
ds.maxWait=60000
#配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒
ds.timeBetweenEvictionRunsMillis=60000
#配置一個連線在池中最小生存的時間,單位是毫秒
ds.minEvictableIdleTimeMillis=300000
# dataSource2
jd.jdbc.url=jdbc:mysql://192.168.1.120:3306/jdsc?useUnicode=true&characterEncoding=utf-8
jd.jdbc.username=root
jd.jdbc.password=123456
四、測試切換
注意:測試服務類的包路徑,因為只有被AOP攔截的到的指定的Service才會進行資料來源的切換。
package com.dufy.web.service.impl.Data1ServiceImpl;
/**
* 使用 dataSourc1 ,配置dataSourc1的資料來源
* @author:duf
* @version:1.0.0
* @date 2018/12/17
*/
@Service
@DataSourceType(value = DataSourceConstants.DATASOURCE_1)
public class Data1ServiceImpl implements Data1Service {
@Resource
private Data1Mapper data1Mapper;
@Override
public List<String> selectCaseByUpdateTime(String name) {
List<String> data1 = data1Mapper.selectData1(name);
return data1;
}
}
package com.dufy.web.service.impl.Data2ServiceImpl;
/**
* 使用 dataSourc2 ,配置dataSourc2的資料來源
* @author:duf
* @version:1.0.0
* @date 2018/12/17
*/
@Service
@DataSourceType(value = DataSourceConstants.DATASOURCE_2)
public class Data2ServiceImpl implements Data2Service {
@Resource
private Data2Mapper data2Mapper;
@Override
public List<String> selectCaseByUpdateTime(String name) {
List<String> data2 = data2Mapper.selectData2(name);
return data2;
}
}
通過測試後發現,兩個Service伺服器分別呼叫自己的配置的資料來源進行資料的獲取!
五、實現原理
基於AbstractRoutingDataSource
實現 多資料來源配置,通過AOP來進行資料來源的靈活切換。AOP的相關原理這裡不做說明,就簡單說一下 AbstractRoutingDataSource
,它是如何切換資料來源的!
首先我們繼承 AbstractRoutingDataSource
它是一個抽象類,然後要實現它裡面的一個抽象方法。
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean
實現了InitializingBean
,InitializingBean介面為bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是繼承該介面的類,在初始化bean的時候都會執行該方法。
在AbstractRoutingDataSource
中afterPropertiesSet
方法的實現。
public void afterPropertiesSet() {
if (this.targetDataSources == null) {
throw new IllegalArgumentException("Property 'targetDataSources' is required");
} else {
this.resolvedDataSources = new HashMap(this.targetDataSources.size(
相關推薦
【教程】Spring+Mybatis環境配置多資料來源
一、簡要概述
在做專案的時候遇到需要從兩個資料來源獲取資料,專案使用的Spring + Mybatis環境,看到網上有一些關於多資料來源的配置,自己也整理學習一下,然後自動切換實現從不同的資料來源獲取資料功能。
二、程式碼詳解
2.1 DataSourceConstants
【Java mail 入門教程】第一講 環境配置
本人一直在找相關的完整的java mail入門教程,可惜沒有較好和完整的,所以自學自編出一套完整的入門教程,我不敢說自己寫得很好,很完善,畢竟這也算是處女作。
本教程是本人學習java mail 的一些學習心得,大部分為原創,一些資料是我收集後整理出來給大家參考的。如
【MVC】Spring MVC常用配置
solver errors 自動裝箱 property byte mco 驗證 c基礎 form表單 一、SpringMVC基礎入門,創建一個HelloWorld程序
1.首先,導入SpringMVC需要的jar包。
2.添加Web.xml配置文件中關於Spring
【odoo】windows初始環境配置
1.安裝Python
下載安裝Python,本機裝的2.7.9。
開啟官網:https://www.python.org/ →Downloads根據自己的需要下載對應作業系統版本(odoo使用2.7即可)
分享網盤:連結:http://pan.baidu.com/s/1o8bm3jk 密
【記錄】spring中一個介面多個實現類
重構遇到個小問題,記錄下:
錯誤資訊:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field xxxService in com.ali
【SpringBoot】spring-boot-自動配置原理
思考:配置檔案到底能寫什麼?怎麼寫?自動配置原理;
1.自動配置原理
springboot自動配置主演通過@EnableConfiguration,@Conditional,@EnableConfigurationProperties或者@ConfiguraionProp
Spring Boot + MyBatis + Pagehelper 配置多資料來源
package top.cmnbgy.springbootibatismulidatasource.dataSource;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionF
【jupyter】:anaconda環境下多python版本下安裝不同python版本的jupyter和spyder
1.經過嘗試,Windows下還是直接anaconda navigator下選擇不同python環境安裝比較方便。
2.jupyter預設目錄的更改
1 選擇一個用於存放config檔案的資料夾
2 在cmd中進入該資料夾的路徑
3在cmd中 輸
Spring Boot 2.x基礎教程:Spring Data JPA的多資料來源配置
[上一篇](http://blog.didispace.com/spring-boot-learning-21-3-7/)我們介紹了在使用JdbcTemplate來做資料訪問時候的多資料來源配置實現。接下來我們繼續學習如何在使用Spring Data JPA的時候,完成多資料來源的配置和使用。
## 新增多
springboot使用mybatis如何配置多資料來源
本篇部落格提供一個工程想連線多個數據庫進行業務查詢,在原先的單個數據庫上進行配置實現多個數據庫的使用,對於springboot以及mybatis不在此進行展開介紹,只需要把程式碼按照步驟一步步貼上進你的專案,調整一下就能實現;
簡單介紹單個數據源配置
pom檔案匯入依賴
<
Spring Boot + MyBatis + Druid環境下配置多資料來源
專案中採用Spring Boot + MyBatis + Druid的架構,在原資料來源的基礎上需要新增一個新的資料來源。
除錯期間,發現添加了SqlSessionFactoryBean後,原資料來源有一部分欄位無法取值,後發現是application.yml中的配置失效,
【轉】JRebel外掛安裝配置與破解啟用(多方案)詳細教程
JRebel 介紹
IDEA上原生是不支援熱部署的,一般更新了 Java 檔案後要手動重啟 Tomcat 伺服器,才能生效,浪費不少生命啊。目前對於idea熱部署最好的解決方案就是安裝JRebel外掛,這樣不論是更新 class 類還是更新 Spring 配置檔案都能做
【Java】一次SpringMVC+ Mybatis 配置多資料來源經歷
現在在維護的是學校的一款資訊服務APP的後臺,最近要開發一些新功能,其中一個就是加入學校電影院的線上購票。線上購票實際上已經有一套系統了,但是是外包給別人開發的,我們拿不到程式碼只能拿到資料庫,並且也不一定能很好的相容之前的程式碼,所以需要基於這個資料庫來進行新的開發。
【spring】spring boot的配置文件application.yml
odi ini druid convert use pac map location leg spring: datasource:# 本地庫 url: jdbc:mysql://192.168.18.7:3306/shiptrackersmart?useUni
Spring+SpringMVC+Mybatis環境配置
gmv name adsi rtu hand odi 初始 技術 監聽 文件目錄展示
resouce目錄展示
src目錄展示
WebRoot目錄展示
jdbc.propertise
driver=com.mysql.jdbc.Driver
url=jdbc:m
【轉】spring cloud eureka 參數配置
lint 客戶 就會 大於 health 微服務 表示 安全 穩定 eureka.client.registry-fetch-interval-seconds
表示eureka client間隔多久去拉取服務註冊信息,默認為30秒,對於api-gateway,如果要迅速獲
【01】Spring Boot配置文件相關
其他 boot 默認 命令行參數 標註 yml 環境 獲取 rop 1、Spring Boot 獲取屬性的屬性源,優先級從高到低
(1)命令行參數
(2)java:comp/env裏的JNDI屬性
(3)JVM系統屬性
(4)操作系統的環境變量
(5)隨機生成的的帶rand
求購個偽基站多少錢【教程】
聯系 事業 政府 指數 機構 民生 創新 通過 顯示 求購個偽基站多少錢【咨/詢:1587乄6350乄964 】微.信已開通網頁 打不開請直接聯系,我們有實體,本報廣州7月12日電??(記者羅艾樺)日前,廣州市公益慈善聯合會發布首份區域慈善指數報告。 報告
【webpack結合React開發環境配置】React開發環境配置之Webpack結合Babel8.x版本安裝的正確姿勢(Webpack最新版4.x結合Babel8.x環境配置步驟)
1. 安裝cnpmnpm install -g cnpm --registry=https://registry.npm.taobao.org【使用淘寶映象】2. 初始化package.json檔案cnpm init -y3. 安裝webpackcnpm install -d webpack webpack-
【Java】一次SpringMVC+ ibatis 配置多資料來源經歷
問題
如何在一個web專案中使用兩個資料來源,並且不同的介面可以按需選擇資料庫。
方案
最開始的做法
因為我們的專案用的是ibatis作為ORM框架,在其配置檔案中可以配置資料來源資訊,原始配置如下:
spring-application.xm