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

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

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

    Junky's IT Notebook

    統(tǒng)計(jì)

    留言簿(8)

    積分與排名

    WebSphere Studio

    閱讀排行榜

    評(píng)論排行榜

    Open Session In View探討(轉(zhuǎn))

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

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

    ??? Open Session In View request session 綁定到當(dāng)前 thread 期間一直保持 hibernate session open 狀態(tài),使 session request 的整個(gè)期間都可以使用,如在 View 層里 PO 也可以 lazy loading 數(shù)據(jù),如 ${ company.employees } 。當(dāng) View 層邏輯完成后,才會(huì)通過 Filter doFilter 方法或 Interceptor postHandle 方法自動(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則等于沒用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過程中提及一個(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ì)把獲取回來的session的flush mode 設(shè)為FlushMode.NEVER。然后把該sessionFactory綁定到TransactionSynchronizationManager,使request的整個(gè)過程都使用同一個(gè)session,在請(qǐng)求過后再接除該sessionFactory的綁定,最后closeSessionIfNecessary根據(jù)該session是否已和transaction綁定來決定是否關(guān)閉session。在這個(gè)過程中,若HibernateTemplate 發(fā)現(xiàn)自當(dāng)前session有不是readOnly的transaction,就會(huì)獲取到FlushMode.AUTO Session,使方法擁有寫權(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)限,如果沒有transaction,并且沒有另外人為地設(shè)flush model的話,則doFilter的整個(gè)過程都是Flush.NEVER。所以受transaction保護(hù)的方法有寫權(quán)限,沒受保護(hù)的則沒有。

    										
    采用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開頭的方法擁有可寫的事務(wù),如果當(dāng)前有某個(gè)方法,如命名為importExcel(),則因沒有transaction而沒有寫權(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看起來還不錯(cuò),其實(shí)副作用不少??椿厣厦鍻penSessionInViewFilter的doFilterInternal方法代碼,這個(gè)方法實(shí)際上是被父類的doFilter調(diào)用的,因此,我們可以大約了解的OpenSessionInViewFilter調(diào)用流程: request(請(qǐng)求)->open session并開始transaction->controller->View(Jsp)->結(jié)束transaction并close session.

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

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

    posted on 2007-03-06 14:01 junky 閱讀(526) 評(píng)論(0)  編輯  收藏 所屬分類: spring

    主站蜘蛛池模板: 国产一区二区三区免费观在线| 久久精品国产亚洲av瑜伽| 久久嫩草影院免费看夜色| 免费人成在线观看网站视频| 亚洲爆乳精品无码一区二区| 成人片黄网站色大片免费| 美女视频黄免费亚洲| 成人免费视频观看无遮挡| 亚洲欧美日韩久久精品| 天天操夜夜操免费视频| 国产av无码专区亚洲av毛片搜| 国产婷婷高清在线观看免费| 精品免费AV一区二区三区| 亚洲M码 欧洲S码SSS222| 国产免费区在线观看十分钟| 亚洲VA成无码人在线观看天堂 | 亚洲乱码中文字幕综合234| 全部一级一级毛片免费看| 久久乐国产精品亚洲综合| 免费一级毛片在线播放视频| 亚洲精品无码久久久久久久| 九九精品免费视频| 97公开免费视频| 91亚洲精品第一综合不卡播放| 222www免费视频| 亚洲国产精品无码中文lv| 四虎影视免费永久在线观看| 一个人看的www视频免费在线观看| 国产精品亚洲一区二区三区在线| 无码国产精品一区二区免费vr | 成年女性特黄午夜视频免费看| 亚洲精品无码久久久久秋霞| 日本一区二区三区日本免费| 中文字幕看片在线a免费| 亚洲无砖砖区免费| 免费一看一级毛片| 国产麻豆成人传媒免费观看| 国产成人精品亚洲2020| 久久国产成人亚洲精品影院| 无码国产精品一区二区免费式直播 | 亚洲av无码成h人动漫无遮挡|