<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Cyh的博客

    Email:kissyan4916@163.com
    posts - 26, comments - 19, trackbacks - 0, articles - 220

    一、spring+hibernate時(shí)使用hibernate的延遲加載功能時(shí)存在的問(wèn)題

    spring是一個(gè)設(shè)計(jì)層面的框架,他解決的是業(yè)務(wù)邏輯層和其他各層的松耦合問(wèn)題,因此它將面向接口的編程思想貫穿整個(gè)系統(tǒng)應(yīng)用。Spring的orm框架用來(lái)集成其他持久層框架,比如hibernate,spring-orm框架對(duì)hibernate的session進(jìn)行了封裝,我們可以很方便的通過(guò)繼承這個(gè)封裝類(lèi)HibernateDAOSupport并注入hibernate的sessionFactory完成初始化,并調(diào)用其內(nèi)置對(duì)象HibernateTemplate的封裝方法來(lái)調(diào)用session的API而不用考慮到session的初始化和關(guān)閉以及事務(wù)處理等系統(tǒng)操作,這也是AOP思想的一種體現(xiàn)。Hibernate的延遲加載功能是指獲取某個(gè)實(shí)體對(duì)象時(shí)并不從數(shù)據(jù)庫(kù)中加載他的關(guān)聯(lián)對(duì)象,而在實(shí)際獲取關(guān)聯(lián)對(duì)象的時(shí)候才從數(shù)據(jù)庫(kù)中加載,這樣做很好的節(jié)省了數(shù)據(jù)庫(kù)資源但是前提是必須保持session處于打開(kāi)狀態(tài),在所有操作完成后再關(guān)閉。Spring封裝了session操作后很自然的要做到在方法調(diào)用的前后打開(kāi)和關(guān)閉session,這樣我們?cè)谕ㄟ^(guò)HibernateTemplate的方法來(lái)獲取實(shí)體對(duì)象以后session就已經(jīng)關(guān)閉了,而這時(shí)候在調(diào)用獲取關(guān)聯(lián)對(duì)象的方法的時(shí)候就會(huì)拋出異常:


    二、如何解決

     1openSessionInViewInterceptor

    通過(guò)spring的控制層框架spring-mvc來(lái)處理控制層并通過(guò)攔截器openSessionInViewInterceptor改變spring調(diào)用session的流程。這里介紹最簡(jiǎn)單的spring-mvc的使用方法,首先和struts一樣要定義一個(gè)HttpServlet來(lái)總體控制請(qǐng)求的處理類(lèi)以及容器的初始化,struts是ActionServlet,Spring是DispatcherServlet,如圖:

    如同struts的控制器都繼承于Action類(lèi)一樣,spring的控制器都要實(shí)現(xiàn)controller接口

    我們通過(guò)注入的方式傳入usersDAO進(jìn)行數(shù)據(jù)操作(通常這個(gè)操作應(yīng)該是放到Service層,這里為了方便講解沒(méi)有加入Service層),這個(gè)DAOmyeclipse自動(dòng)生成的原封不動(dòng),這里不再貼出來(lái)了。

    幾句話(huà)的意思很清楚,調(diào)用findByID方法把ID1000的用戶(hù)實(shí)體查出來(lái),這個(gè)時(shí)候按道理session已經(jīng)關(guān)閉了,下面調(diào)用user.getNewses方法獲取這個(gè)用戶(hù)發(fā)布的新聞信息的一個(gè)set集合,打印條數(shù),系統(tǒng)顯示:

    沒(méi)有報(bào)session 已經(jīng)關(guān)閉的錯(cuò)誤,原因是spring-config中作了配置,在配置之前我們要對(duì)spring-mvc做一些初步的了解。

    配合DispatcherServlet我們也要定義相關(guān)的映射,能夠?qū)⒄?qǐng)求跳轉(zhuǎn)到對(duì)應(yīng)的控制器,先看看usersDAO

    然后是我們的控制器LoginSpring,這里沒(méi)有對(duì)跳轉(zhuǎn)作處理,因?yàn)槲覀兊闹攸c(diǎn)不是mvc而是解決延遲加載。

     

    最后是我們的映射和針對(duì)這些控制器所配置的攔截器opensessioninviewinterceptor

    這樣配置了以后管理session的就不是我們的hibernatetemplate了而是我們配置的攔截器,他會(huì)保持session直到我們的控制器做完了所有的事情才關(guān)閉,也就是我們調(diào)用user.getNewses方法的時(shí)候是打開(kāi)的,因此能得到滿(mǎn)意的結(jié)果。

    2openSessionInViewFilter

    當(dāng)我們的系統(tǒng)的控制層要使用struts的時(shí)候,我們就不能使用spring的攔截器了,因個(gè)這個(gè)攔截器是基于DispatcherServlet的,我們只有在web.xml中配置過(guò)濾器來(lái)改變session的流程。首先簡(jiǎn)要介紹一下struts+spring集成,看看struts的配置文件:

    每個(gè)Action的type都設(shè)定為org.springframework.web.struts.DelegatingActionProxy,并在最下面配置spring的配置文件的路徑,當(dāng)我們要使用過(guò)濾器的時(shí)候這個(gè)配置文件必須只存放Action的實(shí)際映射,下面是spring-action.xml,里面只有一個(gè)action:

    這里不需要指定id,只需要指定別名,這個(gè)別名會(huì)自動(dòng)匹配struts配置文件中對(duì)應(yīng)的path, DelegatingActionProxy會(huì)自動(dòng)從插件所配置的spring配置文件中尋找匹配的bean并實(shí)例化,當(dāng)然也會(huì)完成注入的過(guò)程。知道怎么將兩個(gè)框架正和使用以后,我們來(lái)配置過(guò)濾器,見(jiàn)web.xml:

    這里使用過(guò)濾器的時(shí)候一定要附上所有spring配置文件并在web容器(tomcat)啟動(dòng)時(shí)加載和初始化。這里spring-action.xml存放的Struts的Action的映射,spring-config.xml中存放其他的bean。

    最后再看看這個(gè)Action,和上面的一樣的代碼。

    這樣的話(huà)當(dāng)我們使用延遲加載的時(shí)候調(diào)用的就是HibernateTamplate的代理類(lèi),能夠讓Spring在請(qǐng)求開(kāi)始的時(shí)候打開(kāi)Session,響應(yīng)結(jié)束前關(guān)閉Session,這樣就不會(huì)存在Session關(guān)閉的錯(cuò)誤了。但是當(dāng)我們?cè)鰟h改的時(shí)候,又會(huì)出現(xiàn)下面的問(wèn)題:

    為什么會(huì)有這樣的問(wèn)題呢,因?yàn)?/span>Hibernate有自己的事務(wù)策略,我們?cè)?/span>SpringOpenSessionInView中打開(kāi)Session是以只讀的方式來(lái)管理事務(wù),這樣進(jìn)行增刪改的時(shí)候就會(huì)出現(xiàn)錯(cuò)誤。如何解決,先看看Spring的事務(wù)處理。

    三、聲明式事務(wù)處理

    聲明式事務(wù)處理是springAOP思想的一個(gè)擴(kuò)展,事務(wù)處理是一個(gè)典型的系統(tǒng)功能,因此通過(guò)將事務(wù)處理封裝在一個(gè)切面中進(jìn)行處理以分離具體業(yè)務(wù)操作和系統(tǒng)功能的方式是最好的設(shè)計(jì)層面的選擇。

    首先我們要配置一個(gè)PlatformTransactionManager接口的一個(gè)實(shí)現(xiàn)用來(lái)控制事務(wù)流程(commitrollback),如果我們是spring+hibernate,框架集成的話(huà),我們就要配置hibernate專(zhuān)用的PlatformTransactionManager實(shí)現(xiàn):

    我們模擬一個(gè)實(shí)例就是兩個(gè)銀行之間的轉(zhuǎn)賬,MsBankDAO民生銀行DAOZsBankDAO招商銀行DAO。這兩個(gè)DAO都是用myeclipse生成,這里不作介紹,我們的業(yè)務(wù)邏輯對(duì)象BankBOtransferMoney方法來(lái)完成這個(gè)轉(zhuǎn)賬操作:

    其中if語(yǔ)句中的兩個(gè)操作就是一個(gè)典型的粗粒度事務(wù),我們使用聲明的方式來(lái)進(jìn)行事務(wù)處理就無(wú)需在這里面加入任何關(guān)于事務(wù)的代碼。

    既然是使用AOP代理BO,我們就得有一個(gè)BankBOImpl的代理類(lèi):

    然后我們模擬一個(gè)事故:

    將民生銀行的修改方法拋出一個(gè)錯(cuò)誤

    我們要傳入被代理類(lèi)的接口以及實(shí)現(xiàn),建一個(gè)主函數(shù)來(lái)測(cè)試一下:

    注意這里要通過(guò)代理類(lèi)boProxy來(lái)返回BankBO的一個(gè)臨時(shí)實(shí)現(xiàn),運(yùn)行結(jié)果:


    在查看數(shù)據(jù)庫(kù)中的數(shù)據(jù)并沒(méi)有改變。

    四、解決ReadOnly事務(wù)策略問(wèn)題

    繼續(xù)第二節(jié)我們的問(wèn)題,Hibernate的事務(wù)策略是需要配置的,Spring為了能以AOP的方式來(lái)管理事務(wù),就必須提供Hibernate事務(wù)策略和事務(wù)操作的封裝,也就是我們上面提供的PlatFormTransactionManager接口的Hibernate持久層實(shí)現(xiàn)HibernateTransactionManager,

    Spring在處理事務(wù)的時(shí)候會(huì)將這個(gè)底層的封裝體傳到TransactionTemplate進(jìn)行初始化事務(wù)處理流程和參數(shù),我們?cè)诳碒ibernateTeamplat是我們所熟知的Hibernate的Session的API的封裝,他的父類(lèi)HibernateAccessor中已經(jīng)定義好了5種Hibernate的事務(wù)策略,其中就有Flush_NEVER策略和FLUSH_AUTO等策略,如果我們平時(shí)增刪改的時(shí)候沒(méi)有用到HibernateTamplate就會(huì)在操作的時(shí)候由Hibernate來(lái)管理事務(wù),但這個(gè)時(shí)候由于Opensessioninview的緣故為了防止在延遲加載的時(shí)候改動(dòng)持久層刷新策略已經(jīng)被設(shè)定為Flush_Never,也就是說(shuō)增刪改的時(shí)候也會(huì)以只讀的刷新模式來(lái)處理,這當(dāng)然會(huì)報(bào)錯(cuò),按照異常所說(shuō)的要把前者換成后者就行了,但這樣就沒(méi)辦法保證延遲加載的時(shí)候的安全性,因?yàn)楹苡锌赡苓@個(gè)PO對(duì)象會(huì)被傳到View層被隨意改動(dòng),如果能夠在讀的時(shí)候只讀,在寫(xiě)的時(shí)候由能夠及時(shí)刷新就能解決問(wèn)題了,如果是編程式事務(wù)處理的話(huà),我們就必須分別在查詢(xún)和增刪改的時(shí)候更換刷新模式,這將會(huì)很麻煩,還好Spring提供了聲明式事務(wù)處理,提供了一種擴(kuò)展性很高的解決方案。解決的方法很簡(jiǎn)單,讓Spring來(lái)全權(quán)管理事務(wù),在省事的同時(shí)也更好的劃分了層次的關(guān)系,避免了Service層涉及事務(wù)策略這類(lèi)的系統(tǒng)功能,將AOP思想體現(xiàn)的淋漓盡致。看看配置:

     

    Find開(kāi)頭的方法被設(shè)定為只讀,其他方法設(shè)定為auto(默認(rèn)),讓所有Service結(jié)尾的類(lèi)的方法都處在事務(wù)中(包括不需要事務(wù)的方法),雖然消耗了一定的系統(tǒng)資源,但卻讓我們不必再為事務(wù)的問(wèn)題操心,把精力集中到業(yè)務(wù)邏輯中。


     

     

     

     

     

     

     

     

     

     

     


     



     


     


     

     

     

     

     



                                                                                                           --    學(xué)海無(wú)涯
            

    Feedback

    # re: Spring+Hibernate延遲和聲明式事務(wù)處理最終解決方案[未登錄](méi)  回復(fù)  更多評(píng)論   

    2009-08-24 15:57 by 胡炯
    謝謝了。。。非常感謝

    # re: Spring+Hibernate延遲和聲明式事務(wù)處理最終解決方案  回復(fù)  更多評(píng)論   

    2010-01-05 02:04 by 竹泉
    非常感謝,太好的文章了
    主站蜘蛛池模板: 无码国产精品一区二区免费式芒果| 亚洲欧洲国产综合| www.亚洲精品| 国产美女无遮挡免费视频网站| 日美韩电影免费看| 国产无遮挡吃胸膜奶免费看视频 | 国产特黄一级一片免费 | 亚洲人成电影在线观看青青| 亚洲卡一卡2卡三卡4麻豆| 国产成人精品日本亚洲网址 | 亚洲尹人香蕉网在线视颅| 亚洲午夜在线电影| 亚洲成人动漫在线观看| 亚洲综合精品成人| 国产精品亚洲专区在线播放| 一级女性全黄久久生活片免费| 一个人免费观看日本www视频| 99re6在线视频精品免费| 特级无码毛片免费视频尤物| 8x8x华人永久免费视频| 人禽杂交18禁网站免费| 日韩精品视频免费观看| 亚洲精品美女久久久久99小说| 亚洲情XO亚洲色XO无码| 亚洲嫩模在线观看| 亚洲AV无码无限在线观看不卡| 美女视频黄a视频全免费网站一区 美女视频黄a视频全免费网站色 | 热99re久久精品精品免费| 亚洲AⅤ永久无码精品AA| 国产精品亚洲精品日韩已满| 亚洲精品视频免费在线观看| 亚洲欧美乱色情图片| 午夜在线免费视频 | yellow视频免费在线观看| 一区二区免费视频| 女人18毛片a级毛片免费视频| 国产一区二区免费在线| 亚洲av中文无码乱人伦在线播放| 亚洲人成在线中文字幕| 色多多A级毛片免费看| 91大神在线免费观看|