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

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

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

    Junky's IT Notebook

    統計

    留言簿(8)

    積分與排名

    WebSphere Studio

    閱讀排行榜

    評論排行榜

    Open Session In View探討(轉)

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

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

    ??? Open Session In View request session 綁定到當前 thread 期間一直保持 hibernate session open 狀態,使 session request 的整個期間都可以使用,如在 View 層里 PO 也可以 lazy loading 數據,如 ${ company.employees } 。當 View 層邏輯完成后,才會通過 Filter doFilter 方法或 Interceptor postHandle 方法自動關閉 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默認為true,若設為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過程中提及一個錯誤:

    										
    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里的幾個方法

    										
    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的時候,會把獲取回來的session的flush mode 設為FlushMode.NEVER。然后把該sessionFactory綁定到TransactionSynchronizationManager,使request的整個過程都使用同一個session,在請求過后再接除該sessionFactory的綁定,最后closeSessionIfNecessary根據該session是否已和transaction綁定來決定是否關閉session。在這個過程中,若HibernateTemplate 發現自當前session有不是readOnly的transaction,就會獲取到FlushMode.AUTO Session,使方法擁有寫權限。

    										
    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轉為Flush.AUTO,擁有insert,update,delete操作權限,如果沒有transaction,并且沒有另外人為地設flush model的話,則doFilter的整個過程都是Flush.NEVER。所以受transaction保護的方法有寫權限,沒受保護的則沒有。

    										
    采用spring的事務聲明,使方法受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>

    對于上例,則以save,add,update,remove開頭的方法擁有可寫的事務,如果當前有某個方法,如命名為importExcel(),則因沒有transaction而沒有寫權限,這時若方法內有insert,update,delete操作的話,則需要手動設置flush model為Flush.AUTO,如

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

    ?????盡管Open Session In View看起來還不錯,其實副作用不少。看回上面OpenSessionInViewFilter的doFilterInternal方法代碼,這個方法實際上是被父類的doFilter調用的,因此,我們可以大約了解的OpenSessionInViewFilter調用流程: request(請求)->open session并開始transaction->controller->View(Jsp)->結束transaction并close session.

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

    Open Session In View是個雙刃劍,放在公網上內容多流量大的網站請慎用。

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

    主站蜘蛛池模板: 毛片a级毛片免费观看品善网| 男女一进一出抽搐免费视频| 五月婷婷在线免费观看| 亚洲Av永久无码精品三区在线| 国产午夜精品理论片免费观看| 国产v亚洲v天堂无码网站| 国产色爽免费无码视频| 亚洲日韩区在线电影| 黄页网站免费在线观看| 亚洲欧美成人av在线观看| 日韩a级毛片免费视频| 久久精品国产亚洲AV未满十八| 又大又硬又爽免费视频| 又长又大又粗又硬3p免费视频 | 免费可以在线看A∨网站| 亚洲中文字幕无码久久2020 | 亚洲AV无码国产精品麻豆天美| 久久精品国产大片免费观看| 亚洲视频日韩视频| 中文字幕av无码无卡免费 | av午夜福利一片免费看久久| 亚洲无人区一区二区三区| 国产精品免费高清在线观看| 亚洲欧洲国产综合| 四虎影视免费在线| 久久久WWW免费人成精品| 亚洲精品熟女国产| 免费v片在线观看无遮挡| a级毛片免费完整视频| 亚洲伊人久久大香线焦| 免费一级毛片正在播放| 在线成人精品国产区免费| 亚洲中文无码线在线观看| 免费日韩在线视频| 男人都懂www深夜免费网站| 亚洲国产日韩综合久久精品| 免费国产怡红院在线观看| 久久爰www免费人成| 亚洲精品无码一区二区| 亚洲日本乱码在线观看| 国产精品成人免费一区二区 |