欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

再析在spring框架中解決多數(shù)據(jù)源的問題

系統(tǒng) 1638 0

在前面我寫了《 如何在 spring 框架中解決多數(shù)據(jù)源的問題 》,通過設(shè)計(jì)模式中的 Decorator 模式在 spring 框架中解決多數(shù)據(jù)源的問題,得到了許多網(wǎng)友的關(guān)注。在與網(wǎng)友探討該問題的過程中,我發(fā)現(xiàn)我的方案并不完善,它只解決了一部分問題。

總結(jié)多數(shù)據(jù)源的問題,其實(shí)它需要分為以下三種情況:各個(gè)數(shù)據(jù)源的數(shù)據(jù)結(jié)構(gòu)不同、各個(gè)數(shù)據(jù)源的數(shù)據(jù)結(jié)構(gòu)相同、各個(gè)數(shù)據(jù)源的數(shù)據(jù)結(jié)構(gòu)部分相同又有部分不同。對(duì)于第二種情況,各個(gè)數(shù)據(jù)源的數(shù)據(jù)結(jié)構(gòu)相同,我們使用一個(gè) sessionFactory ,而在 sessionFactory 中通過 MultiDataSource 來動(dòng)態(tài)切換數(shù)據(jù)源,應(yīng)當(dāng)是一個(gè)不錯(cuò)的方案,既解決了多個(gè) sessionFactory 對(duì)相同的值對(duì)象重復(fù)裝載對(duì)內(nèi)存的浪費(fèi),又使數(shù)據(jù)源的切換對(duì)客戶程序透明,簡化了代碼的實(shí)現(xiàn)和對(duì)客戶程序的影響。但是,對(duì)于第一種情況,各個(gè)數(shù)據(jù)源的數(shù)據(jù)結(jié)構(gòu)不同,運(yùn)用這樣的方案存在潛在風(fēng)險(xiǎn)。

對(duì)于各個(gè)數(shù)據(jù)源的數(shù)據(jù)結(jié)構(gòu)不同的情況,使用一個(gè) sessionFactory 而在這個(gè) sessionFactory 中動(dòng)態(tài)切換數(shù)據(jù)源,可能造成數(shù)據(jù)訪問的張冠李戴。譬如,數(shù)據(jù)源 A 有表 T 而數(shù)據(jù)源 B 沒有,可能造成客戶程序在訪問表 T 的時(shí)候卻嘗試去連接數(shù)據(jù)源 B ,因?yàn)榭蛻舫绦蛟L問哪個(gè)數(shù)據(jù)源是在程序運(yùn)行期間由客戶程序決定的,因此這樣的錯(cuò)誤是很難發(fā)現(xiàn)的。也許客戶程序的一個(gè)不經(jīng)意的錯(cuò)誤就可能造成錯(cuò)誤。解決這個(gè)問題的方法有兩個(gè):一是嚴(yán)格要求客戶程序不要寫錯(cuò),這當(dāng)然是可以做到的,但作為框架設(shè)計(jì)者,另一個(gè)解決方法是在框架中就避免出現(xiàn)這樣的情況。因此我祭出了 MultiSessionFactory 的方案來解決各個(gè)數(shù)據(jù)源的數(shù)據(jù)結(jié)構(gòu)不同的多數(shù)據(jù)源問題。

問題的分析

MultiDataSource 的方案一樣, MultiSessionFactory 同樣是在 spring 框架下調(diào)用 ApplicationContext getBean() 方法而不會(huì)另外創(chuàng)建 beanFacoty ,也同樣使用 Decorator 模式來處理切換的問題。 MultiSessionFactory 的對(duì)象關(guān)系如圖:

?


再析在spring框架中解決多數(shù)據(jù)源的問題
?

在該方案中, SessionFactory 就是 Hibernate org.hibernate.SessionFactory 接口, Decorator 就是 MultiSessionFactory SessionFactory1 SessionFactory2 往往是 spring org.springframework.orm.hibernate3.LocalSessionFactoryBean 。細(xì)心的朋友可能會(huì)注意,實(shí)際上 LocalSessionFactoryBean 并不是 SessionFactory 的實(shí)現(xiàn),這個(gè)方案是否有問題呢?這個(gè)問題其實(shí)也一直困擾了我好久,最后我發(fā)現(xiàn),我們通過 ApplicationContext getBean() 得到一個(gè) LocalSessionFactoryBean 的時(shí)候其實(shí)并不是真正地得到了它,而是得到了一個(gè) SessionFactory ,因?yàn)? spring LocalSessionFactoryBean 重寫了 getObject() ,使其返回的是 SessionFactory 。一個(gè)簡單的明證就是, HibernateDaoSupport sessionFactory 屬性的類型是 SessionFactory ,而我們?cè)? spring 配置的時(shí)候注入的卻是 LocalSessionFactoryBean

方案的實(shí)現(xiàn)

在整個(gè)這個(gè)方案中,我們需要實(shí)現(xiàn)的只有 MultiSessionFactory 類和我們可愛的 Spserver ,總共就兩個(gè)類,然后呢就是一些 spring 的配置,就完成了。

MultiSessionFactory 實(shí)現(xiàn)了 SessionFactory ,同時(shí)為了得到 AplicationContext 而實(shí)現(xiàn)了 ApplicationContextAware MultiSessionFactory 的代碼如下:

java 代碼

  1. public ? class ?MultiSessionFactory? implements ?SessionFactory,?ApplicationContextAware?{ ??
  2. ???? private ? static ? final ? long ?serialVersionUID?=?2064557324203496378L; ??
  3. ???? private ? static ? final ?Log?log?=?LogFactory.getLog(MultiSessionFactory. class ); ??
  4. ???? private ?ApplicationContext?applicationContext?=? null ; ??
  5. ???? private ?SessionFactory?sessionFactory?=? null ; ??
  6. ???? public ?ApplicationContext?getApplicationContext()?{ ??
  7. ???????? return ?applicationContext; ??
  8. ????} ??
  9. ???? public ? void ?setApplicationContext(ApplicationContext?applicationContext)?{ ??
  10. ??????? this .applicationContext?=?applicationContext; ??
  11. ????} ??
  12. ???? public ?SessionFactory?getSessionFactory(String?sessionFactoryName)?{ ??
  13. ???????log.debug( "sessionFactoryName:" +sessionFactoryName); ??
  14. ??????? try { ??
  15. ??????????? if (sessionFactoryName== null ||sessionFactoryName.equals( "" )){ ??
  16. ?????????????? return ?sessionFactory; ??
  17. ???????????} ??
  18. ??????????? return ?(SessionFactory) this .getApplicationContext().getBean(sessionFactoryName); ??
  19. ???????} catch (NoSuchBeanDefinitionException?ex){ ??
  20. ??????????? throw ? new ?DaoException( "There?is?not?the?sessionFactory?
  21. ???????} ??
  22. ????} ??
  23. ??
  24. ???? public ?SessionFactory?getSessionFactory()?{ ??
  25. ???????String?sessionFactoryName?=?SpObserver.getSp(); ??
  26. ??????? return ?getSessionFactory(sessionFactoryName); ??
  27. ????} ??
  28. ??
  29. ???? public ? void ?setSessionFactory(SessionFactory?sessionFactory)?{ ??
  30. ??????? this .sessionFactory?=?sessionFactory; ??
  31. ????} ??
  32. ??
  33. ???? //?SessionFactory接口需要實(shí)現(xiàn)的方法 ??
  34. ??
  35. ...... ??
  36. ??
  37. }??

MultiSessionFactory 的完整代碼見我提供的附件。 setSessionFactory() 實(shí)際上是設(shè)定的默認(rèn) sessionFactory ,它在 spring 裝載的時(shí)候調(diào)用,其對(duì)應(yīng)的數(shù)據(jù)源應(yīng)當(dāng)是主數(shù)據(jù)源,即項(xiàng)目初始化中需要讀取初始化數(shù)據(jù)的數(shù)據(jù)源。在任何多數(shù)據(jù)源項(xiàng)目中,都應(yīng)當(dāng)有一個(gè)存放初始化數(shù)據(jù)、系統(tǒng)維護(hù)數(shù)據(jù)、用戶權(quán)限數(shù)據(jù)的數(shù)據(jù)源,這就是主數(shù)據(jù)源。因此 MultiSessionFactory 的配置應(yīng)當(dāng)這樣寫:

xml 代碼

  1. < bean ? id = "sessionFactory" ? class = "com.htxx.service.dao.MultiSessionFactory" > ??
  2. ???? < property ? name = "sessionFactory" > < ref ? bean = "hostSessionFactory" /> property > ?
  3. > ??

SpServer 的寫法與 《如何在 spring 框架中解決多數(shù)據(jù)源的問題》 中的一樣,我就不再累贅了。

另外,在 spring 配置中配置多個(gè)數(shù)據(jù)源,每個(gè)數(shù)據(jù)源對(duì)應(yīng)一個(gè) sessionFactory ,這個(gè)對(duì)應(yīng)的 sessionFactory 中的值對(duì)象應(yīng)當(dāng)是該數(shù)據(jù)源的值對(duì)象。客戶程序在執(zhí)行數(shù)據(jù)訪問前,通過調(diào)用 SpServer putSp() 方法,告訴 MultiSessionFactory 需要切換到哪個(gè) sessionFactory ,然后執(zhí)行數(shù)據(jù)訪問。這樣,不同數(shù)據(jù)源的值對(duì)象通過放在不同的 sessionFactory 中,避免了張冠李戴的情況。具體的示例見附件的 MultiSessionFactoryTest

另外的方案

也許有些朋友對(duì)以上方案還不滿意,因?yàn)樵趫?zhí)行數(shù)據(jù)訪問前畢竟還要多做一步指定 sessionFactory 的工作。實(shí)際上,對(duì)于各個(gè)數(shù)據(jù)源的數(shù)據(jù)結(jié)構(gòu)不同的項(xiàng)目,一個(gè)值對(duì)象應(yīng)當(dāng)使用哪個(gè)數(shù)據(jù)源有一個(gè)非常確定的對(duì)應(yīng)關(guān)系。如果通過配置文件將值對(duì)象與它的 sessionFactory 對(duì)應(yīng)起來,那么我們?cè)趫?zhí)行數(shù)據(jù)訪問的時(shí)候傳遞的是哪個(gè)值對(duì)象, MultiSessionFactory 馬上就可以去找到對(duì)應(yīng)的 sessionFactory 。這個(gè)方案你可以通過 AOP 來制作一個(gè)攔截器攔截所有諸如 save() delete() get() load() 等方法來實(shí)現(xiàn),也可以擴(kuò)展 HibernateDaoSupport 來實(shí)現(xiàn)。這樣的方案使客戶程序甚至都不用知道他是在操作的一個(gè)多數(shù)據(jù)源系統(tǒng)。當(dāng)然,這個(gè)方案感興趣的朋友可以自己去實(shí)現(xiàn)。

另外,在這個(gè)方案中的核心是運(yùn)用 Decorator 設(shè)計(jì)模式來解決切換 sessionFactory 的目的,即 MultiSessionFactory 的實(shí)現(xiàn)。至于通過什么方式來通知 MultiSessionFactory 應(yīng)當(dāng)切換到哪個(gè) SessionFactory ,可以根據(jù)不同項(xiàng)目的情況自由選擇。我在這里給大家提供了通過 SpOberver 和建立值對(duì)象與 sessionFactory 關(guān)系的配置文件這兩個(gè)方案,你也可以有自己的方案解決。

第三種情況的解決方案

前面我已經(jīng)給出了第一種和第二種情況的解決方案:各個(gè)數(shù)據(jù)源的數(shù)據(jù)結(jié)構(gòu)不同的情況用 MultiSessionFactory 解決;各個(gè)數(shù)據(jù)源的數(shù)據(jù)結(jié)構(gòu)相同的情況用 MultiDataSource 解決。那么第三種情況,各個(gè)數(shù)據(jù)源的數(shù)據(jù)結(jié)構(gòu)部分相同又有部分不同,又應(yīng)當(dāng)如何解決呢?當(dāng)然是將 MultiSessionFactory MultiDataSource 結(jié)合起來解決。對(duì)于數(shù)據(jù)結(jié)構(gòu)不同的部分,其分別創(chuàng)建各自的 sessionFactory 然后通過 MultiSessionFactory 來切換,而對(duì)于數(shù)據(jù)結(jié)構(gòu)相同的部分,建立共同的 sessionFactory 和多個(gè)不同的 dataSource 然后通過 MultiDataSource 來切換就可以了。

還有的朋友問到這樣的方案其事務(wù)處理和二級(jí)緩存的情況。這個(gè)方案是在 spring 框架下的解決方案,其事務(wù)處理的能力也是由 spring 的能力來決定的。目前 spring 要處理跨數(shù)據(jù)庫的事務(wù)處理是通過 JTA 來實(shí)現(xiàn)的,這種方式在該方案中同樣可以實(shí)現(xiàn),朋友們可以試一試。另外,本方案能使用二級(jí)緩存嗎?當(dāng)然可以。對(duì)于 MultiSessionFactory 當(dāng)然沒有任何問題,它通過不同的 sessionFactory 分離開了不同的數(shù)據(jù)源和值對(duì)象,我們可以毫無顧忌地使用。對(duì)于 MultiDataSource 來說,就有點(diǎn)問題了。 MultiDataSource 使多個(gè)數(shù)據(jù)源使用共同的 sessionFactory ,因此它仿佛就是將多個(gè)數(shù)據(jù)源在邏輯上合并為一個(gè)數(shù)據(jù)源。正因?yàn)槿绱耍覀冃枰WC對(duì)于同一個(gè)表在所有數(shù)據(jù)源中都要主鍵唯一。什么意思呢?數(shù)據(jù)源 A 和數(shù)據(jù)源 B 都有表 T ,如果數(shù)據(jù)源 A 中的表 T 擁有 ID 001 的一條數(shù)據(jù),那么在數(shù)據(jù)源 B 的表 T 中就不能有 ID 001 的記錄。如果你總是通過 MultiDataSource 來執(zhí)行表的插入操作,并且使用uuid.hex生成主鍵,這當(dāng)然不會(huì)有問題。但如果你有通過其它方式插入表的操作,你應(yīng)當(dāng)保證這樣的唯一性。另外,對(duì)于查詢的操作,緩存中存放的既可能是數(shù)據(jù)源 A 的數(shù)據(jù),也可能是數(shù)據(jù)源 B 的數(shù)據(jù),因此你應(yīng)當(dāng)對(duì)數(shù)據(jù)有一個(gè)規(guī)劃。對(duì)于表 T 的數(shù)據(jù),哪些應(yīng)當(dāng)插入到數(shù)據(jù)源 A 中,哪些應(yīng)當(dāng)插入到 B 中,應(yīng)當(dāng)有一個(gè)定義。假如是通過不同單位來決定插入哪個(gè)數(shù)據(jù)源,那么在查詢數(shù)據(jù)源 A 的表 T 是,應(yīng)當(dāng)增加條件只查詢數(shù)據(jù)源 A 應(yīng)當(dāng)有的單位而排除調(diào)其它單位。如此這樣,你只要注意到這兩個(gè)問題,你就可以放心大膽地使用二級(jí)緩存。

?

?

再析在spring框架中解決多數(shù)據(jù)源的問題


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产精品人妻无码久久久郑州 | 日本人麻豆| 手机在线看片国产日韩生活片 | 高清国语自产拍免费视频国产 | 中国一级特黄真人毛片 | 日韩欧美色 | 久草在线视频资源站 | 国内精品一区二区在线观看 | 好吊妞gao988在线播放 | 呦呦在线视频 | 日本高清无卡码一区二区久久 | 91一区二区三区 | 性夜黄a爽爽免费视频国产 尤物tv在线 | 99精品在线观看 | 视频一区国产 | 波多久久夜色精品国产 | 欧美日韩亚洲高清不卡一区二区三区 | 波多野中文字幕s | 色综合天天综合高清网国产 | 欧美国产日韩在线观看 | 狠狠色依依成人婷婷九月 | 一个色综合亚洲伊人久久 | 97麻豆精品国产自产在线观看 | 亚洲精品无码成人A片九色播放 | 精品免费国产一区二区三区四区 | 一区二区三区波多野结衣 | 亚洲欧美日韩在线一区 | 男人电影天堂 | 精品久久久久久久久久 | 婷婷人人爽人人做人人添 | 日韩在线黄色 | 97精品一区二区 | 无码色情影片视频在线看免费 | 四虎网站在线观看 | 人人香蕉 | 国产日产亚洲欧美综合另类 | 久久福利青草狠狠午夜 | 91麻豆国产极品在线观看洋子 | 亚洲福利一区 | 国产亚洲福利精品一区 | 亚洲欧美在线播放 |