久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

關(guān)于OpenSessionInView

 旭龍 2013-01-09

當(dāng)hibernate+spring配合使用的時(shí)候,如果設(shè)置了lazy=true,那么在讀取數(shù)據(jù)的時(shí)候,,當(dāng)讀取了父數(shù)據(jù)后,,hibernate會(huì)自動(dòng)關(guān)閉session,,這樣,,當(dāng)要使用子數(shù)據(jù)的時(shí)候,系統(tǒng)會(huì)拋出lazyinit的錯(cuò)誤,,這時(shí)就需要使用spring提供的 OpenSessionInViewFilter,

OpenSessionInViewFilter主要是保持Session狀態(tài)知道request將全部頁面發(fā)送到客戶端,,這樣就可以解決延遲加載帶來的問題

3、說說Webwork中使用OpenSessionInView的注意事項(xiàng)

web.xml中的配置要注意先后順序,,OpenSessionInViewFilter要在Webwork的filter前面,,否則系統(tǒng)會(huì)報(bào)錯(cuò)。

代碼

  1. <filter>  
  2.         <filter-name>opensession</filter-name>  
  3.         <filter-class>  
  4.               org.springframework.orm.hibernate3.support.OpenSessionInViewFilter   
  5.         </filter-class>  
  6.         <init-param>  
  7.             <param-name>singleSession</param-name>  
  8.             <param-value>true</param-value>  
  9.         </init-param>  
  10.         <init-param>  
  11.             <param-name>sessionFactoryBeanName</param-name>  
  12.             <param-value>mySessionFactory</param-value>    
  13.         </init-param>  
  14.     </filter>  
  15.         
  16.     <filter>  
  17.         <filter-name>webwork</filter-name>  
  18.         <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>  
  19.     </filter>  
  20.          <filter-mapping>  
  21.       <filter-name>opensession</filter-name>  
  22.       <url-pattern>/*</url-pattern>    
  23.     </filter-mapping>  
  24.     <filter-mapping>  
  25.         <filter-name>webwork</filter-name>  
  26.         <url-pattern>/*</url-pattern>  
  27.     </filter-mapping>  

對(duì)于OpenSessionInView的配置中,,singleSession應(yīng)該設(shè)置為true,,表示一個(gè)request只能打開一個(gè) session,如果設(shè)置為false的話,,session可以被打開多個(gè),,這時(shí)在update、delete的時(shí)候會(huì)出現(xiàn)打開多個(gè)session的異常,。

但是當(dāng)設(shè)置為true的時(shí)候,,系統(tǒng)的性能會(huì)因?yàn)橛脩舻木W(wǎng)絡(luò)狀況受到影響,當(dāng)request在生成頁面完成后,,session才會(huì)被釋放,,所以如果用戶的網(wǎng)絡(luò)狀況比較差,那么連接池中的鏈接會(huì)遲遲不被回收,,造成內(nèi)存增加,,系統(tǒng)性能受損。但是如果不用這種方法的話,,lazy模式有體現(xiàn)不出它的優(yōu)點(diǎn),,用?不用,??jī)呻y啊

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

在沒有使用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配置而已,。

    OpenSessionInView在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

  3. class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">

  4. <property >

  5. <ref bean="sessionFactory"/>

  6. </property>

  7. </bean>

  8. <bean

  9. class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

  10. <property >

  11. <list>

  12. <ref bean="openSessionInViewInterceptor"/>

  13. </list>

  14. </property>

  15. <property >

  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í)間長(zhǎng),,另一方面可能是網(wǎng)速慢,服務(wù)器與用戶間傳輸時(shí)間久,。當(dāng)大量這樣的情況出現(xiàn)時(shí),,就有連接池連接不足,造成頁面假死現(xiàn)象,。

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

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 由于OpenSessionInViewFilter把session綁在當(dāng)前線程上,,導(dǎo)致session的生命周期比事務(wù)要長(zhǎng),這期間所有事務(wù)性操作都在復(fù)用這同一個(gè)session,,由此產(chǎn)生了一些“怪問題”:

1.出現(xiàn)如下錯(cuò)誤:

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

  分析原因:OpenSessionInViewFilter 在把session綁在當(dāng)前線程上的時(shí)候,會(huì)把session的flush mode 設(shè)為FlushMode.NEVER,,因此,如果某個(gè)方法沒有事務(wù)或者有只讀事務(wù),,則不能對(duì)session做insert,update,delete操作,,除非事先把session的flush mode手動(dòng)設(shè)為auto

方案:

1、將singleSession設(shè)為false,,這樣只要改 web.xml,,缺點(diǎn)是Hibernate Session的Instance可能會(huì)大增,使用的JDBC Connection量也會(huì)大增,,如果Connection Pool的maxPoolSize設(shè)得太小,,很容易就出問題。<!-- singleSession默認(rèn)為true,若設(shè)為false則等于沒用OpenSessionInView -->

2,、在控制器中自行管理Session的FlushMode,,麻煩的是每個(gè)有Modify的Method都要多幾行程式

  session.setFlushMode(FlushMode.AUTO); 

  session.update(user); 

  session.flush(); 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多