欧美三区_成人在线免费观看视频_欧美极品少妇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)論
主站蜘蛛池模板: 日韩欧美中文字幕视频 | 日韩av中文 | 色网在线播放 | 91看片淫黄大片一级在线观看 | 亚洲一区二区三区视频 | 国产人成精品一区二区三 | 一区二区三区免费在线观看 | 成人国产精品 | 99色这里只有精品 | 梦中人在线观看免费完整版 | 久久国产乱子免费精品 | 欧美成人免费在线视频 | 欧美综合在线观看 | 欧美视频一区 | 久久se精品一区精品二区 | 成人无码T髙潮喷水A片小说 | 香蕉视频免费网站 | 精品人成 | 国产成人精品一区二区三区视频 | 欧美一区二区三区中文字幕 | 日本欧美久久久久免费播放网 | 久久亚洲一级α片 | 五月婷婷丁香在线 | 欧美国产激情二区三区 | 日韩一区精品视频 | 欧美一级毛片在线播放 | 韩国资源视频一区二区三区 | 国产一级免费不卡 | 久久精品欧美一区 | 国产精品一区久久 | 91九色免费视频 | 国产精品理论片在线观看 | 久久精品国产欧美成人 | 日韩精品一区二区三区第95 | 精品午夜寂寞影院在线观看 | 欧美一区二区三区gg高清影视 | 天天成人综合网 | 日韩欧美亚洲一区 | 色噜噜狠狠先锋影音久久 | 成人国产精品一区二区毛片在线 | 中文天堂网|