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

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

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

    lqxue

    常用鏈接

    統(tǒng)計(jì)

    book

    tools

    最新評(píng)論

    Open Session In View

    http://www.54bk.com/user1/2690/archives/2006/2006122116259.html

    Open Session In View解決session.close問(wèn)題
    ssuupv 發(fā)表于 2006-12-21 16:25:00
      在沒(méi)有使用Spring提供的Open Session In View情況下,因需要在service(or Dao)層里把session關(guān)閉,所以lazy loading true的話,要在應(yīng)用層內(nèi)把關(guān)系集合都初始化,如 company.getEmployees(),否則Hibernatesession already closed Exception;    Open Session In View提供了一種簡(jiǎn)便的方法,較好地解決了lazy loading問(wèn)題.

        它有兩種配置方式OpenSessionInViewInterceptorOpenSessionInViewFilter(具體參看SpringSide),功能相同,只是一個(gè)在web.xml配置,另一個(gè)在application.xml配置而已。

        Open Session In Viewrequestsession綁定到當(dāng)前thread期間一直保持hibernate sessionopen狀態(tài),使sessionrequest的整個(gè)期間都可以使用,如在View層里PO也可以lazy loading數(shù)據(jù),如 ${ company.employees }。當(dāng)View 層邏輯完成后,才會(huì)通過(guò)FilterdoFilter方法或InterceptorpostHandle方法自動(dòng)關(guān)閉session。

                            
    OpenSessionInViewInterceptor配置
    1. <beans>
    2. <bean name="openSessionInViewInterceptor"
    3. class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
    4. <property name="sessionFactory">
    5. <ref bean="sessionFactory"/>
    6. </property>
    7. </bean>
    8. <bean id="urlMapping"
    9. class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    10. <property name="interceptors">
    11. <list>
    12. <ref bean="openSessionInViewInterceptor"/>
    13. </list>
    14. </property>
    15. <property name="mappings">
    16. ...
    17. </property>
    18. </bean>
    19. ...
    20. </beans>
                            
    OpenSessionInViewFilter配置
    1. <web-app>
    2. ...
    3. <filter>
    4. <filter-name>hibernateFilter</filter-name>
    5. <filter-class>
    6. org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    7. </filter-class>
    8. <!-- singleSession默認(rèn)為true,若設(shè)為false則等于沒(méi)用OpenSessionInView -->
    9. <init-param>
    10. <param-name>singleSession</param-name>
    11. <param-value>true</param-value>
    12. </init-param>
    13. </filter>
    14. ...
    15. <filter-mapping>
    16. <filter-name>hibernateFilter</filter-name>
    17. <url-pattern>*.do</url-pattern>
    18. </filter-mapping>
    19. ...
    20. </web-app>

    很多人在使用OpenSessionInView過(guò)程中提及一個(gè)錯(cuò)誤:

                            
    1. org.springframework.dao.InvalidDataAccessApiUsageException: Write operations
    2. are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into
    3. FlushMode.AUTO or remove 'readOnly' marker from transaction definition

    看看OpenSessionInViewFilter里的幾個(gè)方法

                            
    1. protected void doFilterInternal(HttpServletRequest request,
      HttpServletResponse response,FilterChain filterChain)
      throws ServletException, IOException {
       SessionFactory sessionFactory = lookupSessionFactory();
       logger.debug("Opening Hibernate Session in OpenSessionInViewFilter");
       Session session = getSession(sessionFactory);
       TransactionSynchronizationManager.bindResource(
        sessionFactory, new SessionHolder(session));
       try {
        filterChain.doFilter(request, response);
       }
       finally {
       TransactionSynchronizationManager.unbindResource(sessionFactory);
       logger.debug("Closing Hibernate Session in OpenSessionInViewFilter");
       closeSession(session, sessionFactory);
       }
      }





       
    2. protected Session getSession(SessionFactory sessionFactory)
      throws DataAccessResourceFailureException {
       Session session = SessionFactoryUtils.getSession(sessionFactory, true);
       session.setFlushMode(FlushMode.NEVER);
       return session;
      }

    3. protected
      void closeSession(Session session, SessionFactory sessionFactory)
      throws CleanupFailureDataAccessException {
       SessionFactoryUtils.closeSessionIfNecessary(session, sessionFactory);
      }

         可以看到OpenSessionInViewFilter在getSession的時(shí)候,會(huì)把獲取回來(lái)的session的flush mode 設(shè)為FlushMode.NEVER。然后把該sessionFactory綁定到TransactionSynchronizationManager,使request的整個(gè)過(guò)程都使用同一個(gè)session,在請(qǐng)求過(guò)后再接除該sessionFactory的綁定,最后closeSessionIfNecessary根據(jù)該session是否已和transaction綁定來(lái)決定是否關(guān)閉session。在這個(gè)過(guò)程中,若HibernateTemplate 發(fā)現(xiàn)自當(dāng)前session有不是readOnly的transaction,就會(huì)獲取到FlushMode.AUTO Session,使方法擁有寫(xiě)權(quán)限。

                            
    1. public static void closeSessionIfNecessary(Session session, SessionFactory sessionFactory)
    2. throws CleanupFailureDataAccessException {
    3. if (session == null ||
      TransactionSynchronizationManager.hasResource(sessionFactory)) {
    4. return;
    5. }
    6. logger.debug("Closing Hibernate session");
    7. try {
    8. session.close();
    9. }
    10. catch (JDBCException ex) {
    11. // SQLException underneath
    12. throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex.getSQLException());
    13. }
    14. catch (HibernateException ex) {
    15. throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex);
    16. }
    17. }

        也即是,如果有不是readOnly的transaction就可以由Flush.NEVER轉(zhuǎn)為Flush.AUTO,擁有insert,update,delete操作權(quán)限,如果沒(méi)有transaction,并且沒(méi)有另外人為地設(shè)flush model的話,則doFilter的整個(gè)過(guò)程都是Flush.NEVER。所以受transaction保護(hù)的方法有寫(xiě)權(quán)限,沒(méi)受保護(hù)的則沒(méi)有。

                            
    采用spring的事務(wù)聲明,使方法受transaction控制
    1.   <bean id="baseTransaction"
      class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
                abstract="true">
              <property name="transactionManager" ref="transactionManager"/>
              <property name="proxyTargetClass" value="true"/>
              <property name="transactionAttributes">
                  <props>
                      <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                      <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                      <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
                      <prop key="save*">PROPAGATION_REQUIRED</prop>
                      <prop key="add*">PROPAGATION_REQUIRED</prop>
                      <prop key="update*">PROPAGATION_REQUIRED</prop>
                      <prop key="remove*">PROPAGATION_REQUIRED</prop>
                  </props>
              </property>
          </bean>

    2.     <bean id="userService" parent="baseTransaction">
              <property name="target">
                  <bean class="com.phopesoft.security.service.impl.UserServiceImpl"/>
              </property>
          </bean>

      對(duì)于上例,則以save,add,update,remove開(kāi)頭的方法擁有可寫(xiě)的事務(wù),如果當(dāng)前有某個(gè)方法,如命名為importExcel(),則因沒(méi)有transaction而沒(méi)有寫(xiě)權(quán)限,這時(shí)若方法內(nèi)有insert,update,delete操作的話,則需要手動(dòng)設(shè)置flush model為Flush.AUTO,如

                                  
      1. session.setFlushMode(FlushMode.AUTO);
      2. session.save(user);
      3. session.flush();

           盡管Open Session In View看起來(lái)還不錯(cuò),其實(shí)副作用不少。看回上面OpenSessionInViewFilter的doFilterInternal方法代碼,這個(gè)方法實(shí)際上是被父類(lèi)的doFilter調(diào)用的,因此,我們可以大約了解的OpenSessionInViewFilter調(diào)用流程: request(請(qǐng)求)->open session并開(kāi)始transaction->controller->View(Jsp)->結(jié)束transaction并close session.

           一切看起來(lái)很正確,尤其是在本地開(kāi)發(fā)測(cè)試的時(shí)候沒(méi)出現(xiàn)問(wèn)題,但試想下如果流程中的某一步被阻塞的話,那在這期間connection就一直被占用而不釋放。最有可能被阻塞的就是在寫(xiě)Jsp這步,一方面可能是頁(yè)面內(nèi)容大,response.write的時(shí)間長(zhǎng),另一方面可能是網(wǎng)速慢,服務(wù)器與用戶間傳輸時(shí)間久。當(dāng)大量這樣的情況出現(xiàn)時(shí),就有連接池連接不足,造成頁(yè)面假死現(xiàn)象。

      Open Session In View是個(gè)雙刃劍,放在公網(wǎng)上內(nèi)容多流量大的網(wǎng)站請(qǐng)慎用。


      閱讀全文(302) | 回復(fù)(0) | 引用通告(638) | 編輯
       

      posted on 2007-04-03 08:58 lqx 閱讀(244) 評(píng)論(0)  編輯  收藏


      只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


      網(wǎng)站導(dǎo)航:
       
      主站蜘蛛池模板: 亚洲精品国产品国语在线| 日韩在线视频播放免费视频完整版| 国产精品久久永久免费| 亚洲区日韩精品中文字幕| 亚洲男人的天堂在线va拉文| 在线观看人成视频免费无遮挡| 亚洲欧洲视频在线观看| 免费在线视频一区| 久久久久国色av免费看| 亚洲七久久之综合七久久| 久久久亚洲欧洲日产国码农村| 好吊妞视频免费视频| 国产99久久久久久免费看| 亚洲资源最新版在线观看| 国产精品亚洲美女久久久| 台湾一级毛片永久免费| 国产精品一区二区三区免费| 亚洲综合色7777情网站777| 亚洲精品无码成人片久久| 毛片免费在线播放| 国产拍拍拍无码视频免费| 亚洲av成人中文无码专区| 91亚洲国产成人久久精品网站| 亚洲国产精品成人网址天堂| 男女免费观看在线爽爽爽视频 | 国产嫩草影院精品免费网址| 中文无码成人免费视频在线观看 | 亚洲AV综合色区无码二区爱AV| 亚洲 无码 在线 专区| 在线观看www日本免费网站| eeuss免费天堂影院| 亚洲色大18成人网站WWW在线播放| 国产亚洲成av片在线观看| 亚洲 自拍 另类小说综合图区| 免费视频专区一国产盗摄| 无码专区AAAAAA免费视频| 无遮挡免费一区二区三区| 亚洲youwu永久无码精品| 国产精品亚洲自在线播放页码| 久久亚洲国产午夜精品理论片| 啊灬啊灬别停啊灬用力啊免费看|