spring+mybatis 多數據源整合

原文:http://blog.csdn.net/fhx007/article/details/12530735

----------------------------------------------------------------------------------

直接看spring的配置吧


<!-- 數據源配置 --> ?
<bean id="ds1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> ?
? ? <property name="driverClassName" value="Oracle.jdbc.driver.OracleDriver" /> ?
? ? <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl" /> ?
? ? <property name="username" value="test" /> ?
? ? <property name="password" value="test" /> ?
? ? <property name="defaultAutoCommit" value="false"></property> ?
</bean> ?
??
<bean id="ds2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> ?
? ? <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> ?
? ? <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl" /> ?
? ? <property name="username" value="test" /> ?
? ? <property name="password" value="test" /> ?
? ? <property name="defaultAutoCommit" value="false"></property> ?
</bean> ?
??
?<bean id="dataSource" class="app.platform.mybatis.DynamicDataSource"> ?
? ? <property name="targetDataSources"> ?
? ? ? ? <map key-type="Java.lang.String"> ?
? ? ? ? ? ? <entry value-ref="ds1" key="ds1"></entry> ?
? ? ? ? ? ? <entry value-ref="ds2" key="ds2"></entry> ?
? ? ? ? </map> ?
? ? </property> ?
? ? <property name="defaultTargetDataSource" ref="ds1"></property> ? ? ?<!-- 默認使用ds1的數據源 -->
</bean> ?



<!-- mybatis配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:/mybatis/mybatis-config.xml" />
<property name="mapperLocations" value="classpath*:app/mapper/**/*.xml"/>
</bean>

<!-- 事務管理器配置,單數據源事務 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 事務攔截的類及方法 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="query*" read-only="true" />
<tx:method name="is*" read-only="true" />
<tx:method name="do*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
<tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
<tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
<tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
</tx:attributes>
</tx:advice>
<aop:config proxy-target-class="true">
<aop:advisor pointcut="execution(* app..service..*.*(..))" advice-ref="txAdvice" />
</aop:config>

重點是上面的數據源配置


下面的類是在數據源中用到的

package app.platform.mybatis;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource { ?
? ? @Override ?
? ? protected Object determineCurrentLookupKey() { ?
? ? ? ? return DataSourceContextHolder.getDbType(); ?
? ? } ?
}


package app.platform.mybatis;

public class DataSourceContextHolder { ?
?
? ? private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); ?
??
? ? public static void setDbType(String dbType) { ?
? ? ? ? contextHolder.set(dbType); ?
? ? } ?
??
? ? public static String getDbType() { ?
? ? ? ? return ((String) contextHolder.get()); ?
? ? } ?
??
? ? public static void clearDbType() { ?
? ? ? ? contextHolder.remove(); ?
? ? } ?
} ?


這樣就可以了,下面是一個單元測試的例子

public class Test{

@Autowired
private TestService testService;


@Test ?
public void addTest() throws Exception { ?
? ?User user = new User(); ?
? ?user.setUsername("admin"); ?
? ?user.setPassword("123456"); ?
? ?
? ?DataSourceContextHolder.setDbType("ds2"); ? ? //注意這里在調用service前切換到ds2的數據源
?
? ?testService.add(user); ?
} ?
}


最主要的變化是DynamicDataSource 類,這個類繼承了AbstractRoutingDataSource,我們再繼續考察,發現這個類實現了datasource這個接口。?

再仔細研究,發現我配置了多個數據源給DynamicDataSource,默認的數據源是ds1。?
我們研究下AbstractRoutingDataSource類的代碼,主要是兩個實現datasource的方法?

Java代碼??收藏代碼
  1. public?Connection?getConnection()?throws?SQLException?{??
  2. ????return?determineTargetDataSource().getConnection();??
  3. }??
  4. ??
  5. public?Connection?getConnection(String?username,?String?password)?throws?SQLException?{??
  6. ????return?determineTargetDataSource().getConnection(username,?password);??
  7. }??

根據這段代碼發現主要玄機都在determineTargetDataSource()方法上。?

Java代碼??收藏代碼
  1. protected?DataSource?determineTargetDataSource()?{??
  2. ????????Assert.notNull(this.resolvedDataSources,?"DataSource?router?not?initialized");??
  3. ????????Object?lookupKey?=?determineCurrentLookupKey();??
  4. ????????DataSource?dataSource?=?this.resolvedDataSources.get(lookupKey);??
  5. ????????if?(dataSource?==?null?&&?(this.lenientFallback?||?lookupKey?==?null))?{??
  6. ????????????dataSource?=?this.resolvedDefaultDataSource;??
  7. ????????}??
  8. ????????if?(dataSource?==?null)?{??
  9. ????????????throw?new?IllegalStateException("Cannot?determine?target?DataSource?for?lookup?key?["?+?lookupKey?+?"]");??
  10. ????????}??
  11. ????????return?dataSource;??
  12. ????}??

根據這段代碼發現,首先在使用數據源之前,首先判斷使用數據源的key,也就是我們配置給?
Java代碼??收藏代碼
  1. private?Map<Object,?Object>?targetDataSources;??

這個map中的key值,找到key值之后再找到對應的datasource然后并使用這個數據源。?


從上面我們發現,實際上DynamicDataSource只是在內部封裝了數據源,然后調用它,只不過在內部他加了一些控制而已。(此處不知道是否可以理解為代理模式)?

再深一步想想,此處使用的orm層是mybatis,如果換成hibernate呢,或者jdbctemplate呢。?
實際上這個方法都適用。



本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/539131.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/539131.shtml
英文地址,請注明出處:http://en.pswp.cn/news/539131.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

四管前級怎么去掉高低音音調_一些歌曲音調太高怎么才能唱上去??

展開全部首先得提高肺活量 然后就是練聲&#xff01;怎 樣 練 聲&#xff1a;練聲的目的1&#xff0c;使歌唱發聲系統各器官的肌肉更e68a84e8a2ad62616964757a686964616f31333236373231有力&#xff0c;并能協調一致。2&#xff0c;建立正確的聲音概念。3&#xff0c;擴展音域&…

python繪制星空_用python畫星空源代碼是什么?

用python畫星空源代碼是什么&#xff1f;用python畫星空源代碼是from turtle import *from random import random,randintscreen Screen()width ,height 800,600screen.setup(width,height)screen.title("模擬3D星空")screen.bgcolor("black")screen.mod…

Linux - xshell上傳文件報錯亂碼

xshell上傳文件報錯亂碼&#xff0c;解決方法 rz -be 回車 下載sz filename轉載于:https://www.cnblogs.com/RzCong/p/8600899.html

java元數據是什么_用存儲過程和 JAVA 寫報表數據源有什么弊端?

用存儲過程和 JAVA 寫報表數據源有什么弊端&#xff1f;跟著小編一起來一看一下吧&#xff01;我們在報表開發中經常會使用存儲過程準備數據&#xff0c;存儲過程支持分步計算&#xff0c;可以實現非常復雜的計算邏輯&#xff0c;為報表開發帶來便利。所以&#xff0c;報表開發…

mysql多實例安裝啟動_MySQL多實例安裝啟動

Tips&#xff1a;之前我們的一個實例是mysql3306&#xff0c;我們現在再安裝一個mysql33071。和之前一樣&#xff0c;創建需要的目錄文件夾mkdir -p /data/mysql/mysql3307/{data,logs,tmp}創建完 就給文件授權chown -R mysql:mysql /data/mysql/mysql3307/2.進入mysql3307cd /…

用vhdl實現4位加減法計數器_32位加減法器設計

功能特性設計思路基于一位全加器&#xff0c;設計32位并行加法器。并行加法器中全加器的位數與操作數相同&#xff0c;影響速度&#xff08;延時&#xff09;的主要因素是進位信號的傳遞。主要的高速加法器【1】有基本上都是在超前進位加法器&#xff08;CLA&#xff09;的基礎…

用vim + xdebug 來追蹤thinkphp的執行過程

tree命令的使用幾個有實際應用的參數 -a 這是默認的 -d: 只顯式目錄, 不需要顯式目錄下的文件 -L: 列出顯式的深度. 當前目錄下的所有東西為第一級...在tp下, 有多個Common但是它們的含義不同:Application|- Common (前后臺都使用的公共文件所在目錄)|- Common (公共函數目錄)…

mybatis 中#與$的區別

MyBatis/Ibatis中#和$的區別 #{} 解析的是占位符&#xff1f;可以防止SQL注入&#xff0c;比如打印出來的語句 select * from table where id? 然而${} 則是不能防止SQL注入打印出來的語句 select * from table where id2 實實在在的參數

綠色背景配什么顏色文字_灰色褲子配什么顏色上衣好看

我們許多人都喜歡灰色。灰色是一種很酷的自然色。灰色大氣而沉穩。它介于黑白之間&#xff0c;是一種多用途的顏色&#xff0c;與其他顏色搭配將變得時尚而優雅。那么秋冬季節灰色褲子配什么顏色的上衣好看呢&#xff1f;接下來就來看一組時尚大人的灰色褲子穿搭吧。look1 保溫…

浮柵場效應管 符號_場效應管主要參數與特點,場效應管與其他管子的對比

場效應晶體管(Field Effect Transistor縮寫(FET))簡稱場效應管。主要有兩種類型&#xff1a;結型場效應管(junction FET—JFET)和金屬-氧化物半導體場效應管(metal-oxide semiconductor FET&#xff0c;簡稱MOS-FET)。場效應管由多數載流子參與導電&#xff0c;也稱為單極型晶體…

linux軟鏈接

原文地址&#xff1a;http://biyutong.iteye.com/blog/1445699 ------------------------------------------------------------------------ 實例&#xff1a;ln -s /home/gamestat /gamestat linux下的軟鏈接類似于windows下的快捷方式 ln -s a b 中的 a 就是源文件&am…

MySQL主鍵自增長報duplicate_MySQL使用on duplicate key update引起主鍵不連續自增

innodb_autoinc_lock_mode中有3種模式,0,1,2&#xff0c;數據庫默認是1的情況下,每次使用insert into … on duplicate key update 的時候都會把簡單自增id增加,不管是發生了insert還是updateinnodb_autoinc_lock_mode參數詳解tradition(innodb_autoinc_lock_mode0) 模式&#…

super go_Go 簡單性的價值:來自對 Go 倍加青睞的谷歌軟件工程師的自述

點擊上方藍色“Go語言中文網”關注我們&#xff0c;領全套Go資料&#xff0c;每天學習 Go 語言Go 語言最近幾年逐漸獲得越來越多的開發者的喜歡。在 Go 社區前不久剛剛慶祝Go誕生10周年生日之際&#xff0c;谷歌云軟件工程師 Benjamin Congdon 發表個人博客(11 月 11 日發表)&a…

判斷鼠標是否在元素上_是否清掃保潔、是否霧撒降塵?江城環衛車裝上了北斗,動動鼠標就知道了...

楚天都市報12月1日訊(記者盧成漢 通訊員金嬋 潘婷)環衛車裝上北斗定位系統&#xff0c;它是否上路進行清掃保潔&#xff0c;是否霧撒降塵。城管隊員通過手機或電腦&#xff0c;就可以查到它的運行狀態。1日&#xff0c;東湖高新區城管執法局稱&#xff0c;該區運行的北斗智能環…

Object 對象詳解

2019獨角獸企業重金招聘Python工程師標準>>> 面向對象的核心思想:“找合適的對象&#xff0c;做適合的事情”。 合適的對象&#xff1a; 1. 自己描述類&#xff0c;自己創建對象。 2. sun已經描述了好多常用的類&#xff0c;可以使用這些類創建對象。 API&#xff0…

vi/vim命令

概述 vi: Visual Interface vim: VI iMproved vim模式 有三種&#xff1a; 編輯模式(命令模式) 如&#xff1a;通過命令新增一行&#xff0c;刪除一行&#xff0c;復制一行&#xff0c;光標移動等 輸入模式 輸入模式在屏幕末尾一定有這個“-- INSERT --” 末行模式 ESC&…

python條件判斷true_Python中的True,False條件判斷實例分析

本文實例講述了Python中的True,False條件判斷用法。分享給大家供大家參考。具體分析如下&#xff1a;對于有編程經驗的程序員們都知道條件語句的寫法&#xff1a;以C為例&#xff1a;代碼如下:if (condition){doSomething();}對于Python中的條件判斷語句的寫法則是下面的樣子&a…

python安裝報錯類型_解決Python安裝cryptography報錯問題

解決Python安裝cryptography報錯問題錯誤一&#xff1a;gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -DUSE__THREAD -DHAVE_SYNC_SYNCHRONIZE -I/usr/include/ffi -I/usr/include/libffi -I/usr/include/python2.7 -c c/_cffi…

使用ntpdate校正linux系統的時間

原文地址&#xff1a;http://blog.csdn.net/lixianlin/article/details/7045321 ------------------------------------------------------------------------------------- 當Linux服務器的時間不對的時候&#xff0c;可以使用ntpdate工具來校正時間。 安裝&#xff1a;yum in…

Visual Studio 2017 15.6發布

\看新聞很累&#xff1f;看技術新聞更累&#xff1f;試試下載InfoQ手機客戶端&#xff0c;每天上下班路上聽新聞&#xff0c;有趣還有料&#xff01;\\\微軟發布了Visual Studio 2017的第6次升級。和之前的發布一樣&#xff0c;此次升級包含多項Bug修復和整個IDE使用體驗的改善…