一個(gè)輕量的方案, 令mybatis支持?jǐn)?shù)據(jù)庫(kù)輕兼容

>愛(ài)上mybatis是因?yàn)樽杂勺栽诘膕ql映射, SQL在手, 一切我有的那種感覺(jué)!

>然而由于其非完整ORM框架原因, 導(dǎo)致我們掌握了SQL的自由, 卻失去了ORM兼容多庫(kù)的天然特性

>本文章告訴你, 如何使 mybatis 輕量支持?jǐn)?shù)據(jù)庫(kù)兼容?


` Beacuse of some reason , I write this line , just like because of some reason , you read this line !`

>溫馨提示: 由于此方法過(guò)于簡(jiǎn)單粗暴, 所以面世較晚 , 當(dāng)你的mybatis版本高于3.1時(shí),才可以用哦!

#實(shí)現(xiàn)方式

##第一處

###applicationContext.xml or mybatis-config.xml

####applicationContext.xml


```


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-4.0.xsd">






??class="org.springframework.beans.factory.config.PropertiesFactoryBean">

oracle

mysql

db2

sybase

sqlserver






```

>先配置一個(gè)vendorProperties, 存儲(chǔ)productName和其對(duì)應(yīng)的別名, productName為key, 別名為value , 然后配置一個(gè)databaseIdProvider, 關(guān)聯(lián)vendorProperties, 使其拿到配置. 最后再sqlSessionFactory中添加

> ``即可


####mybatis-config.xml


```


????????"http://mybatis.org/dtd/mybatis-3-config.dtd">

????

????????

????????



????

????????

????????

????????

????????



```

直接加個(gè)``節(jié)點(diǎn)就行了

>友情提示, 使用mybatis-config.xml方式時(shí), 必須確保改配置文件中定義了environments及其transactionManager和dataSource,否則databaseIdProvider將不生效, 也就是說(shuō), 使用spring管理mybatis時(shí), 此方式失效!


##第二處

###UserMapper.xml


```


????????PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

????????"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

????????SELECT *

????????FROM users

ORDER BY id ASC



????????SELECT *

????????FROM users

ORDER BY id ASC



```

>經(jīng)過(guò)本人實(shí)測(cè), mybatis查找 statement 的邏輯是 : 先找有databaseId的, 是否有對(duì)應(yīng)的, [1] 若有, 則直接調(diào)用(友情提示:別強(qiáng)行寫(xiě)2個(gè)相同的databaseId且statement id也相同), [1] 若無(wú), 則查找是否有 未指定databaseId的 statement , [2] 若有, 則調(diào)用, [2] 再?zèng)]有, 就報(bào)錯(cuò)了 !

>也就是說(shuō), 你完全可以以一種數(shù)據(jù)庫(kù)為主, 如MySQL為主, Oracle則是某些模塊使用, 即寫(xiě)xml時(shí), 一般都直接不寫(xiě)databaseId, 唯有Oracle那個(gè)模塊才寫(xiě)上 databaseId="oracle" .比如樓主公司, 就是這種情況! 而另一種情況則是, 整個(gè)項(xiàng)目都需要兼容, 那修改量就相對(duì)大一些, 需要2個(gè)statement分別標(biāo)明不同的databaseId.



#原理簡(jiǎn)單剖析

>經(jīng)過(guò)本人不辭辛苦的查看源碼: SqlSessionFactoryBean, 對(duì)應(yīng)的databaseIdProvider代碼, 最終發(fā)現(xiàn)這么一段代碼:



```

Environment var29 = new Environment(this.environment, this.transactionFactory, this.dataSource);

configuration.setEnvironment(var29);

if(this.databaseIdProvider != null) {

????try {

????????configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));

????} catch (SQLException var22) {

????????throw new NestedIOException("Failed getting a databaseId", var22);

????}

}

```

這段代碼是將dataSource傳給databaseIdProvider,讓databaseIdProvider獲取databaseId,并設(shè)置到mybatis中!

>下面看databaseIdProvider如何獲取databaseId


```

private String getDatabaseProductName(DataSource dataSource) throws SQLException {

????????Connection con = null;


????????String var4;

????????try {

????????????con = dataSource.getConnection();

????????????DatabaseMetaData metaData = con.getMetaData();

????????????var4 = metaData.getDatabaseProductName();

????????} finally {

????????????if(con != null) {

????????????????try {

????????????????????con.close();

????????????????} catch (SQLException var11) {

????????????????????;

????????????????}

????????????}


????????}


????????return var4;

????}

```

原來(lái)最終時(shí)通過(guò)connection.getMetaData.getDatabaseProductName()方法得到一個(gè)東東,就是配置中properties的 key , 然后看下面這段代碼:


```

private String getDatabaseName(DataSource dataSource) throws SQLException {

????????String productName = this.getDatabaseProductName(dataSource);

????????if(this.properties != null) {

????????????Iterator i$ = this.properties.entrySet().iterator();


????????????Entry property;

????????????do {

????????????????if(!i$.hasNext()) {

????????????????????return null;

????????????????}


????????????????property = (Entry)i$.next();

????????????} while(!productName.contains((String)property.getKey()));


????????????return (String)property.getValue();

????????} else {

????????????return productName;

????????}

????}

```

>根據(jù)connection獲得了當(dāng)前數(shù)據(jù)源真實(shí)的productName, 如MySQL, Oracle .而后通過(guò)配置進(jìn)來(lái)的properties判斷是否包含這個(gè) key , 若有進(jìn)行返回! 無(wú)則直接返回productName !


以上的源碼都是分析databaseId時(shí)如何獲取, 如何被設(shè)置到mybatis中的, 至于mybatis如何根據(jù)databaseId判斷對(duì)應(yīng)的statement, 那還不是小意思, 不過(guò)本人小白一個(gè), 沒(méi)有看過(guò)mybatis源碼, 對(duì)其不熟悉, 要找這塊源碼太費(fèi)時(shí)間, 浮躁的社會(huì)我也不能幸免 !

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末聚唐,一起剝皮案震驚了整個(gè)濱河市覆糟,隨后出現(xiàn)的幾起案子燎斩,更是在濱河造成了極大的恐慌,老刑警劉巖乘凸,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡梯啤,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)存哲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)因宇,“玉大人,你說(shuō)我怎么就攤上這事祟偷〔旎” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵肩袍,是天一觀的道長(zhǎng)杭棵。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么魂爪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任先舷,我火速辦了婚禮,結(jié)果婚禮上滓侍,老公的妹妹穿的比我還像新娘蒋川。我一直安慰自己,他們只是感情好撩笆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布捺球。 她就那樣靜靜地躺著,像睡著了一般夕冲。 火紅的嫁衣襯著肌膚如雪氮兵。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天歹鱼,我揣著相機(jī)與錄音泣栈,去河邊找鬼。 笑死弥姻,一個(gè)胖子當(dāng)著我的面吹牛南片,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播庭敦,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼疼进,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了秧廉?” 一聲冷哼從身側(cè)響起伞广,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎定血,沒(méi)想到半個(gè)月后赔癌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡澜沟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年灾票,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片茫虽。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡刊苍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出濒析,到底是詐尸還是另有隱情正什,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布号杏,位于F島的核電站婴氮,受9級(jí)特大地震影響斯棒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜主经,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一荣暮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧罩驻,春花似錦穗酥、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至节吮,卻和暖如春抽高,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背课锌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工厨内, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留祈秕,地道東北人渺贤。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像请毛,于是被迫代替她去往敵國(guó)和親志鞍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容