<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時使用hibernate的延遲加載功能時存在的問題

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


    二、如何解決

     1openSessionInViewInterceptor

    通過spring的控制層框架spring-mvc來處理控制層并通過攔截器openSessionInViewInterceptor改變spring調用session的流程。這里介紹最簡單的spring-mvc的使用方法,首先和struts一樣要定義一個HttpServlet來總體控制請求的處理類以及容器的初始化,struts是ActionServlet,Spring是DispatcherServlet,如圖:

    如同struts的控制器都繼承于Action類一樣,spring的控制器都要實現controller接口

    我們通過注入的方式傳入usersDAO進行數據操作(通常這個操作應該是放到Service層,這里為了方便講解沒有加入Service層),這個DAOmyeclipse自動生成的原封不動,這里不再貼出來了。

    幾句話的意思很清楚,調用findByID方法把ID1000的用戶實體查出來,這個時候按道理session已經關閉了,下面調用user.getNewses方法獲取這個用戶發布的新聞信息的一個set集合,打印條數,系統顯示:

    沒有報session 已經關閉的錯誤,原因是spring-config中作了配置,在配置之前我們要對spring-mvc做一些初步的了解。

    配合DispatcherServlet我們也要定義相關的映射,能夠將請求跳轉到對應的控制器,先看看usersDAO

    然后是我們的控制器LoginSpring,這里沒有對跳轉作處理,因為我們的重點不是mvc而是解決延遲加載。

     

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

    這樣配置了以后管理session的就不是我們的hibernatetemplate了而是我們配置的攔截器,他會保持session直到我們的控制器做完了所有的事情才關閉,也就是我們調用user.getNewses方法的時候是打開的,因此能得到滿意的結果。

    2openSessionInViewFilter

    當我們的系統的控制層要使用struts的時候,我們就不能使用spring的攔截器了,因個這個攔截器是基于DispatcherServlet的,我們只有在web.xml中配置過濾器來改變session的流程。首先簡要介紹一下struts+spring集成,看看struts的配置文件:

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

    這里不需要指定id,只需要指定別名,這個別名會自動匹配struts配置文件中對應的path, DelegatingActionProxy會自動從插件所配置的spring配置文件中尋找匹配的bean并實例化,當然也會完成注入的過程。知道怎么將兩個框架正和使用以后,我們來配置過濾器,見web.xml:

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

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

    這樣的話當我們使用延遲加載的時候調用的就是HibernateTamplate的代理類,能夠讓Spring在請求開始的時候打開Session,響應結束前關閉Session,這樣就不會存在Session關閉的錯誤了。但是當我們增刪改的時候,又會出現下面的問題:

    為什么會有這樣的問題呢,因為Hibernate有自己的事務策略,我們在SpringOpenSessionInView中打開Session是以只讀的方式來管理事務,這樣進行增刪改的時候就會出現錯誤。如何解決,先看看Spring的事務處理。

    三、聲明式事務處理

    聲明式事務處理是springAOP思想的一個擴展,事務處理是一個典型的系統功能,因此通過將事務處理封裝在一個切面中進行處理以分離具體業務操作和系統功能的方式是最好的設計層面的選擇。

    首先我們要配置一個PlatformTransactionManager接口的一個實現用來控制事務流程(commitrollback),如果我們是spring+hibernate,框架集成的話,我們就要配置hibernate專用的PlatformTransactionManager實現:

    我們模擬一個實例就是兩個銀行之間的轉賬,MsBankDAO民生銀行DAOZsBankDAO招商銀行DAO。這兩個DAO都是用myeclipse生成,這里不作介紹,我們的業務邏輯對象BankBOtransferMoney方法來完成這個轉賬操作:

    其中if語句中的兩個操作就是一個典型的粗粒度事務,我們使用聲明的方式來進行事務處理就無需在這里面加入任何關于事務的代碼。

    既然是使用AOP代理BO,我們就得有一個BankBOImpl的代理類:

    然后我們模擬一個事故:

    將民生銀行的修改方法拋出一個錯誤

    我們要傳入被代理類的接口以及實現,建一個主函數來測試一下:

    注意這里要通過代理類boProxy來返回BankBO的一個臨時實現,運行結果:


    在查看數據庫中的數據并沒有改變。

    四、解決ReadOnly事務策略問題

    繼續第二節我們的問題,Hibernate的事務策略是需要配置的,Spring為了能以AOP的方式來管理事務,就必須提供Hibernate事務策略和事務操作的封裝,也就是我們上面提供的PlatFormTransactionManager接口的Hibernate持久層實現HibernateTransactionManager,

    Spring在處理事務的時候會將這個底層的封裝體傳到TransactionTemplate進行初始化事務處理流程和參數,我們在看HibernateTeamplat是我們所熟知的Hibernate的Session的API的封裝,他的父類HibernateAccessor中已經定義好了5種Hibernate的事務策略,其中就有Flush_NEVER策略和FLUSH_AUTO等策略,如果我們平時增刪改的時候沒有用到HibernateTamplate就會在操作的時候由Hibernate來管理事務,但這個時候由于Opensessioninview的緣故為了防止在延遲加載的時候改動持久層刷新策略已經被設定為Flush_Never,也就是說增刪改的時候也會以只讀的刷新模式來處理,這當然會報錯,按照異常所說的要把前者換成后者就行了,但這樣就沒辦法保證延遲加載的時候的安全性,因為很有可能這個PO對象會被傳到View層被隨意改動,如果能夠在讀的時候只讀,在寫的時候由能夠及時刷新就能解決問題了,如果是編程式事務處理的話,我們就必須分別在查詢和增刪改的時候更換刷新模式,這將會很麻煩,還好Spring提供了聲明式事務處理,提供了一種擴展性很高的解決方案。解決的方法很簡單,讓Spring來全權管理事務,在省事的同時也更好的劃分了層次的關系,避免了Service層涉及事務策略這類的系統功能,將AOP思想體現的淋漓盡致。看看配置:

     

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


     

     

     

     

     

     

     

     

     

     

     


     



     


     


     

     

     

     

     



                                                                                                           --    學海無涯
            

    Feedback

    # re: Spring+Hibernate延遲和聲明式事務處理最終解決方案[未登錄]  回復  更多評論   

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

    # re: Spring+Hibernate延遲和聲明式事務處理最終解決方案  回復  更多評論   

    2010-01-05 02:04 by 竹泉
    非常感謝,太好的文章了
    主站蜘蛛池模板: 久久精品国产亚洲AV麻豆王友容 | 亚洲国产精品无码成人片久久| 国产精品国产亚洲区艳妇糸列短篇| 成年午夜视频免费观看视频| 99热亚洲色精品国产88| 久久99九九国产免费看小说| 456亚洲人成在线播放网站| 无码国产精品一区二区免费I6| 77777午夜亚洲| 免费看国产一级片| 一级毛片aaaaaa视频免费看| 亚洲热线99精品视频| 九九美女网站免费| 亚洲日韩乱码中文无码蜜桃臀| 114一级毛片免费| 亚洲一卡一卡二新区无人区| 九月婷婷亚洲综合在线| 中文无码日韩欧免费视频| 亚洲VA中文字幕不卡无码| 日本免费xxxx色视频| 亚洲性无码一区二区三区| 亚洲精品和日本精品| 一级毛片全部免费播放| 亚洲高清视频在线| 亚洲欧洲久久av| 免费国产污网站在线观看15| 亚洲熟妇av午夜无码不卡| 亚洲日本中文字幕天堂网| 久久久免费精品re6| 亚洲欧洲无卡二区视頻| 亚洲一级特黄无码片| 最近免费最新高清中文字幕韩国 | 国产免费AV片在线观看| 亚洲精品亚洲人成在线播放| 亚洲av无码天堂一区二区三区| 日韩视频免费在线观看| 亚洲国产精品无码久久98| 国产精一品亚洲二区在线播放| 国产精品成人免费视频网站京东 | 亚洲国产精品无码久久一区二区| 日韩毛片免费无码无毒视频观看|