博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring+Hibernate中的(FlushMode.NEVER)错误产生及解决
阅读量:4068 次
发布时间:2019-05-25

本文共 6776 字,大约阅读时间需要 22 分钟。

<p>Spring+Hibernate中的(FlushMode.NEVER)错误产生及解决<br><a href="http://www.firnow.com">www.firnow.com</a> 时间 : 2007-10-18 作者:佚名 编辑:本站 点击: 1597 [ 评论 ]<br>-<br>-</p>
<p>在没有使用Spring提供的Open Session In View情况下,因需要在service(or Dao)层里把session关闭,所以lazy loading 为true的话,要</p>
<p>在应用层内把关系集合都初始化,如 company.getEmployees(),否则Hibernate抛session already closed Exception; Open Session In </p>
<p>View提供了一种简便的方法,较好地解决了lazy loading问题.</p>
<p> 它有两种配置方式OpenSessionInViewInterceptor和OpenSessionInViewFilter(具体参看SpringSide),功能相同,只是一个在web.xml配</p>
<p>置,另一个在application.xml配置而已。</p>
<p> Open Session In View在request把session绑定到当前thread期间一直保持hibernate session在open状态,使session在request的整个期</p>
<p>间都可以使用,如在View层里PO也可以lazy loading数据,如 ${ company.employees }。当View 层逻辑完成后,才会通过Filter的doFilter</p>
<p>方法或Interceptor的postHandle方法自动关闭session。</p>
<p></p>
<p>OpenSessionInViewInterceptor配置<beans> <br><bean name="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor"> </p>
<p><br><property name="sessionFactory"> <br><ref bean="sessionFactory"/> <br></property> <br></bean> <br><bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <br><property name="interceptors"> <br><list> <br><ref bean="openSessionInViewInterceptor"/> <br></list> <br></property> <br><property name="mappings"> <br>... <br></property> <br></bean> <br>... <br></beans> <br>OpenSessionInViewFilter配置<br><web-app><br>... <br><filter> <br><filter-name>hibernateFilter</filter-name> <br><filter-class> <br>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter <br></filter-class> <br><!-- singleSession默认为true,若设为false则等于没用OpenSessionInView --> <br><init-param> <br><param-name>singleSession</param-name> <br><param-value>true</param-value> <br></init-param> <br></filter> <br>... <br><filter-mapping> <br><filter-name>hibernateFilter</filter-name> <br><url-pattern>*.do</url-pattern> <br></filter-mapping><br>... <br></web-app> <br>很多人在使用OpenSessionInView过程中提及一个错误:</p>
<p>org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode </p>
<p>(FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition 看看</p>
<p>OpenSessionInViewFilter里的几个方法</p>
<p>protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,FilterChain filterChain) throws </p>
<p>ServletException, IOException <br>{ <br>SessionFactory sessionFactory = lookupSessionFactory(); <br>logger.debug("Opening Hibernate Session in OpenSessionInViewFilter"); <br>Session session = getSession(sessionFactory); <br>TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session)); <br>try<br>{  filterChain.doFilter(request, response); <br>} <br>finally <br>{ <br>TransactionSynchronizationManager.unbindResource(sessionFactory); logger.debug("Closing Hibernate Session in </p>
<p>OpenSessionInViewFilter"); <br>closeSession(session, sessionFactory); <br>}<br>} <br>protected Session getSession(SessionFactory sessionFactory)throws DataAccessResourceFailureException <br>{ <br>Session session = SessionFactoryUtils.getSession(sessionFactory, true); <br>session.setFlushMode(FlushMode.NEVER); <br>return session;<br>}<br>protected void closeSession(Session session, SessionFactory sessionFactory)throws CleanupFailureDataAccessException<br>{ <br>SessionFactoryUtils.closeSessionIfNecessary(session, sessionFactory);<br>} <br>可以看到OpenSessionInViewFilter在getSession的时候,会把获取回来的session的flush mode 设为FlushMode.NEVER。<br>然后把该sessionFactory绑定到TransactionSynchronizationManager,使request的整个过程都使用同一个session,<br>在请求过后再接除该sessionFactory的绑定,最后closeSessionIfNecessary根据该session是否已和transaction绑定来决定是否关闭session</p>
<p>。在这个过程中,若HibernateTemplate 发现自当前session有不是readOnly的transaction,就会获取到FlushMode.AUTO Session,使方法拥</p>
<p>有写权限。</p>
<p>public static void closeSessionIfNecessary(Session session, SessionFactory sessionFactory) throws </p>
<p>CleanupFailureDataAccessException <br>{ <br>if (session == null || TransactionSynchronizationManager.hasResource(sessionFactory)) { <br>return; <br>} <br>logger.debug("Closing Hibernate session"); <br>try { <br>session.close(); <br>} <br>catch (<br>JDBCException ex) <br>{ <br>// SQLException underneath <br>throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex.getSQLException()); <br>} <br>catch (HibernateException ex) <br>{ <br>throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex); <br>} <br>} <br>也即是,如果有不是readOnly的transaction就可以由Flush.NEVER转为Flush.AUTO,拥有insert,update,delete操作权限,如果没有</p>
<p>transaction,并且没有另外人为地设flush model的话,则doFilter的整个过程都是Flush.NEVER。所以受transaction保护的方法有写权限,</p>
<p>没受保护的则没有。</p>
<p>采用spring的事务声明,使方法受transaction控制 <br><bean id="baseTransaction" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" </p>
<p>abstract="true"> <br><property name="transactionManager" ref="transactionManager"/> <br><property name="proxyTargetClass" value="true"/> <br><property name="transactionAttributes"> <br><props> <br><prop key="get*"><br>PROPAGATION_REQUIRED,readOnly<br></prop> <br><prop key="find*"><br>PROPAGATION_REQUIRED,readOnly<br></prop> </p>
<p><prop key="load*">PROPAGATION_REQUIRED,readOnly<br></prop> <br><prop key="save*">PROPAGATION_REQUIRED</prop> <br><prop key="add*">PROPAGATION_REQUIRED</prop> <br><prop key="update*">PROPAGATION_REQUIRED</prop> <br><prop key="remove*">PROPAGATIO</p>
<p><br>Spring+Hibernate中的(FlushMode.NEVER)错误产生及解决<br><a href="http://www.firnow.com">www.firnow.com</a> 时间 : 2007-10-18 作者:佚名 编辑:本站 点击: 1598 [ 评论 ]<br>-<br>-<br>N_REQUIRED</prop> <br></props> <br></property> <br></bean> <br><bean id="userService" parent="baseTransaction"> <br><property name="target"> <br><bean class="com.phopesoft.security.service.impl.UserServiceImpl"/> <br></property> <br></bean> <br>对于上例,则以save,add,update,remove开头的方法拥有可写的事务,如果当前有某个方法,如命名为importExcel(),则因没有transaction</p>
<p>而没有写权限,这时若方法内有insert,update,delete操作的话,则需要手动设置flush model为Flush.AUTO,如<br>session.setFlushMode(FlushMode.AUTO); <br>session.save(user); <br>session.flush(); <br>尽管Open Session In View看起来还不错,其实副作用不少。看回上面OpenSessionInViewFilter的doFilterInternal方法代码,这个方法实际</p>
<p>上是被父类的doFilter调用的,因此,我们可以大约了解的OpenSessionInViewFilter调用流程: request(请求)->open session并开始</p>
<p>transaction->controller->View(Jsp)->结束transaction并close session.<br>一切看起来很正确,尤其是在本地开发测试的时候没出现问题,但试想下如果流程中的某一步被阻塞的话,那在这期间connection就一直被占</p>
<p>用而不释放。最有可能被阻塞的就是在写Jsp这步,一方面可能是页面内容大,response.write的时间长,另一方面可能是网速慢,服务器与用</p>
<p>户间传输时间久。当大量这样的情况出现时,就有连接池连接不足,造成页面假死现象。</p>
<p>Open Session In View是个双刃剑,放在公网上内容多流量大的网站请慎用 </p>
<p><br><a href="http://www.firnow.com):http://dev.firnow.com/course/3_program/java/javajs/20071018/77920.html"></a></p>

转载地址:http://mcaji.baihongyu.com/

你可能感兴趣的文章
hd disk / disk raid / disk io / iops / iostat / iowait / iotop / iometer
查看>>
project ASP.NET
查看>>
Linux + OS SUSE 11 / OpenSUSE 11
查看>>
net monitor nagios / cacti / solarwinds / tivoli netcool / Vyatta
查看>>
monitorServer IBM Tivoli Enterprise Monitor Server
查看>>
hd Aruba wifi / honor
查看>>
db db2 v9.7 / 9.8
查看>>
JAVA JDK / JRE / SDK IBM & Oracle
查看>>
db db2 v8.2
查看>>
my games / BF3 / GTA5 / NFS18 / sanguowushuang6 / RA2 / KOF97 / FIFA
查看>>
project ERP_SAP R3 / SAP ECC / mySap
查看>>
hd CPU
查看>>
my read_Japan
查看>>
OS + Linux Interview
查看>>
OS + Unix IBM AIX 5L capability optimization nmon
查看>>
UNIX + OS IBM AIX AS/400
查看>>
my read rss_news
查看>>
IBM Tivoli
查看>>
net browser console
查看>>
IBM WebSphere Extended Deployment
查看>>