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

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

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

    OpenSessionInView詳解(面試時常會問到的問題)

    OpenSessionInViewFilter是Spring提供的一個針對Hibernate的一個支持類,其主要意思是在發起一個頁面請求時打開Hibernate的Session,一直保持這個Session,直到這個請求結束,具體是通過一個Filter來實現的。

    由于Hibernate引入了Lazy Load特性,使得脫離Hibernate的Session周期的對象如果再想通過getter方法取到其關聯對象的值,Hibernate會拋出一個LazyLoad的Exception。所以為了解決這個問題,Spring引入了這個Filter,使得Hibernate的Session的生命周期變長。

    首先分析一下它的源碼,可以發現,它所實現的功能其實比較簡單:
    Java代碼

       1. SessionFactory sessionFactory = lookupSessionFactory(request); 
       
    2. Session session = null
       
    3boolean participate = false
       
    4.  
       
    5if (isSingleSession()) { 
       
    6.     // single session mode 
       7.     if (TransactionSynchronizationManager.hasResource(sessionFactory)) { 
       
    8.     // Do not modify the Session: just set the participate flag. 
       9.     participate = true
      
    10.        }    else { 
      
    11.     logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter"); 
      
    12.     session = getSession(sessionFactory); 
      
    13.     TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session)); 
      
    14.     } 
      
    15. } else { 
      
    16.     // deferred close mode 
      17.     if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) { 
      
    18// Do not modify deferred close: just set the participate flag. 
      19.     participate = true
      
    20.     } else { 
      
    21.     SessionFactoryUtils.initDeferredClose(sessionFactory); 
      
    22.     } 
      
    23. } 
      
    24.  
      
    25try { 
      
    26.     filterChain.doFilter(request, response); 
      
    27. } finally { 
      
    28.     if (!participate) { 
      
    29.             if (isSingleSession()) { 
      
    30.                 // single session mode 
      31.         TransactionSynchronizationManager.unbindResource(sessionFactory); 
      
    32.         logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter"); 
      
    33.         closeSession(session, sessionFactory); 
      
    34.     }else { 
      
    35.         // deferred close mode 
      36.         SessionFactoryUtils.processDeferredClose(sessionFactory); 
      
    37.     } 
      
    38. } 
      
    39. } 



     1 SessionFactory sessionFactory = lookupSessionFactory(request);
     2 Session session = null;
     3 boolean participate = false;
     4 
     5 if (isSingleSession()) {
     6     // single session mode
     7     if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
     8     // Do not modify the Session: just set the participate flag.
     9     participate = true;
    10        }    else {
    11     logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");
    12     session = getSession(sessionFactory);
    13     TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
    14     }
    15 else {
    16     // deferred close mode
    17     if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
    18 // Do not modify deferred close: just set the participate flag.
    19     participate = true;
    20     } else {
    21     SessionFactoryUtils.initDeferredClose(sessionFactory);
    22     }
    23 }
    24 
    25 try {
    26     filterChain.doFilter(request, response);
    27 finally {
    28     if (!participate) {
    29                if (isSingleSession()) {
    30                  // single session mode
    31         TransactionSynchronizationManager.unbindResource(sessionFactory);
    32         logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter");
    33         closeSession(session, sessionFactory);
    34     }else {
    35         // deferred close mode
    36         SessionFactoryUtils.processDeferredClose(sessionFactory);
    37     }
    38 }
    39 }


    在上述代碼中,首先獲得SessionFactory,然后通過SessionFactory獲得一個Session。然后執行真正的Action代碼,最后根據情況將Hibernate的Session進行關閉。整個思路比較清晰。

    注意,在這里有個2個Tips:
    1)通過getSession()獲得的這個Session做了一次
    session.setFlushMode(FlushMode.NEVER); 有關FlushMode可以參考一下這篇文章。http://www2.matrix.org.cn/resource/article/2006-10-08/Hibernate+FlushMode+NEVER_312bca85-5699-11db-91a0-d98dff0aec60.html
    2)Spring對拿到的Session做了一次綁定到當前線程的做法,使得這個Session是線程安全的。

    從上述代碼其實可以得到一些對我們的開發有幫助的結論:
    1)如果使用了OpenSessionInView模式,那么Spring會幫助你管理Session的開和關,從而你在你的DAO中通過HibernateDaoSupport拿到的getSession()方法,都是綁定到當前線程的線程安全的Session,即拿即用,最后會由Filter統一關閉。
    2)由于拿到的Hibernate的Session被設置了session.setFlushMode(FlushMode.NEVER); 所以,除非你直接調用session.flush(),否則Hibernate session無論何時也不會flush任何的狀態變化到數據庫。因此,數據庫事務的配置非常重要。(我們知道,在調用org.hibernate.Transaction.commit()的時候會觸發session.flush())我曾經見過很多人在使用OpenSessionInView模式時,都因為沒有正確配置事務,導致了底層會拋出有關FlushMode.NEVER的異常。

    OpenSessionInView這個模式使用比較簡單,也成為了大家在Web開發中經常使用的方法,不過它有時候會帶來一些意想不到的問題,這也是在開發中需要注意的。
    1. 在Struts+Spring+Hibernate環境中,由于配置的問題導致的模式失效
    這個問題以前論壇曾經討論過,可以參考一下下面這個帖子:
    http://www.javaeye.com/topic/15057

    2. OpenSessionInView的效率問題
    這個問題也有人在論壇提出過,Robbin曾經做過具體的測試,可以具體參考一下下面這個帖子:
    http://www.javaeye.com/topic/17501

    3. 由于使用了OpenSessionInView模式后造成了內存和數據庫連接問題
    這個問題是我在生產環境中碰到的一個問題。由于使用了OpenSessionInView模式,Session的生命周期變得非常長。雖然解決了Lazy Load的問題,但是帶來的問題就是Hibernate的一級緩存,也就是Session級別的緩存的生命周期會變得非常長,那么如果你在你的Service層做大批量的數據操作時,其實這些數據會在緩存中保留一份,這是非常耗費內存的。還有一個數據庫連接的問題,存在的原因在于由于數據庫的Connection是和Session綁在一起的,所以,Connection也會得不到及時的釋放。因而當系統出現業務非常繁忙,而計算量又非常大的時候,往往數據連接池的連接數會不夠。這個問題我至今非常頭痛,因為有很多客戶對數據連接池的數量會有限制,不會給你無限制的增加下去。

    4. 使用了OpenSessionInView模式以后取數據的事務問題
    在使用了OpenSessionInView以后,其實事務的生命周期比Session的生命周期來得短,就以為著,其實有相當一部分的查詢是不被納入到事務的范圍內的,此時是否會讀到臟數據?這個問題我至今不敢確認,有經驗的朋友請指教一下。

    最后提一下OpenSessionInView模式的一些替代方案,可以使用OpenSessionInViewInterceptor來代替這個Filter,此時可以使用Spring的AOP配置,將這個Interceptor配置到你所需要的層次上去。另外就是只能使用最古老的Hibernate.initialize()方法進行初始化了。

    posted on 2009-11-24 11:13 MichaelLee 閱讀(562) 評論(0)  編輯  收藏 所屬分類: Spring

    <2009年11月>
    25262728293031
    1234567
    891011121314
    15161718192021
    22232425262728
    293012345

    導航

    統計

    公告

    ====Michael Lee====
    =Java Sofware Engineer=
    =Work @ Beijing=
    ---再煩,也別忘微笑;再急,也要注意語氣;再苦,也別忘堅持;再累,也要愛自己!---
    ---低調做人,你會一次比一次穩健;高調做事,你會一次比一次優秀---
    ---成功的時候不要忘記過去;失敗的時候不要忘記還有未來---

    常用鏈接

    留言簿(2)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 日韩精品无码免费一区二区三区| 高潮毛片无遮挡高清免费| 久久久久久一品道精品免费看 | 中文字幕av免费专区| 久久久无码精品亚洲日韩软件 | 无码人妻久久一区二区三区免费| 亚洲中文字幕久久精品无码喷水 | 国产偷国产偷亚洲高清在线| 免费欧洲美女牲交视频| 九九免费观看全部免费视频| 国产亚洲美女精品久久久| a级大片免费观看| 亚洲人成电影在线天堂| 麻豆视频免费播放| 中日韩亚洲人成无码网站| 国产精品久免费的黄网站| 九九久久精品国产免费看小说| 亚洲精品国产精品乱码不卡√| 99re在线免费视频| 中文字幕乱码亚洲无线三区| www亚洲一级视频com| 精品国产污污免费网站| 亚洲色av性色在线观无码| 国产精品色午夜视频免费看| 美女被免费网站91色| 亚洲精品91在线| 国产小视频在线观看免费| 免费av一区二区三区| 亚洲三级在线播放| 亚洲成a人片在线观看日本麻豆| a级精品九九九大片免费看| 亚洲五月丁香综合视频| 亚洲人成影院在线无码观看| 免费毛片a线观看| 亚洲乱亚洲乱妇24p| 亚洲精品乱码久久久久久久久久久久| 亚洲精品在线免费观看| 一级毛片完整版免费播放一区| 久久亚洲国产精品成人AV秋霞| 日产国产精品亚洲系列| 69影院毛片免费观看视频在线|