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

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

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

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

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

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

    首先分析一下它的源碼,可以發(fā)現(xiàn),它所實現(xiàn)的功能其實比較簡單:
    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。然后執(zhí)行真正的Action代碼,最后根據(jù)情況將Hibernate的Session進行關(guān)閉。整個思路比較清晰。

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

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

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

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

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

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

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

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

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

    導(dǎo)航

    統(tǒng)計

    公告

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

    常用鏈接

    留言簿(2)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产亚洲一区区二区在线| 亚洲av无码国产精品色在线看不卡| 亚洲av永久综合在线观看尤物| 亚洲国产成人精品激情| 337P日本欧洲亚洲大胆艺术图| 免费无码看av的网站| 亚洲av综合色区| 国产AV无码专区亚洲AV麻豆丫| 免费鲁丝片一级在线观看| 亚洲AV香蕉一区区二区三区| 免费看的黄色大片| 亚洲JIZZJIZZ妇女| 精品福利一区二区三区免费视频 | 全免费a级毛片免费看无码| 亚洲欧美日韩中文字幕一区二区三区| 毛片免费观看的视频| 亚洲影院在线观看| 一级毛片无遮挡免费全部| 黄瓜视频高清在线看免费下载| 国产午夜亚洲精品国产| 国产大片91精品免费看3| 2019亚洲午夜无码天堂| 免费无码不卡视频在线观看| 国产成人亚洲精品91专区高清| 亚洲精品人成无码中文毛片| 国产精品国产亚洲区艳妇糸列短篇| 亚洲国产成人乱码精品女人久久久不卡 | 一级特黄aaa大片免费看| 亚洲精品蜜桃久久久久久| 久草免费在线观看视频| 亚洲av成本人无码网站| 在线亚洲精品福利网址导航| 无码人妻一区二区三区免费看 | 久久丫精品国产亚洲av| 野花高清在线电影观看免费视频| 亚洲第一福利视频| 成人毛片免费观看视频在线| 国产精品成人免费观看| 亚洲精品亚洲人成在线麻豆| 3344免费播放观看视频| 亚洲男人天堂影院|