您的位置:首页 > 运维架构

OpenSessionInViewFilter的配置

2010-10-13 14:07 411 查看
今天上午在用到hibernate的一对多的时候,出现了hibernate的延迟加载的异常,以前都是直接配对lazy=“false”,没有用过OpenSessionInViewFilter,只是晚上在宿舍和几位室友聊天的时候,听他们提过。就想用下,结果还真的出现了些许的问题,值得写篇文章来记录下。

首先自然是最web.xml中配置OpenSessionInViewFilter了,如下:没得说,网上一搜一堆的·······

<!-- openSessionInViewFilter配置  -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


这样的话还是不行,部署并启动Tomcat后,测试你会发现出现有以下类似的异常:

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

在用openSessionInView时,如果采用默认的事务管理(就是在spring配置文件里没有配置事务管理),在调用HibernateDaoSupport类里的getHibernateTemplate()里的增删改方法时,会抛出org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.这个错.
第一次看到这个错,肯定会觉得纳闷,它要你修改session的模式,或者移除readOnly marker.但是你从来都没有设置session的模式.

原因:spring2.0里面的OpenSessionInViewFilter的getSession方法中会对session的flushMode设定一个默认为NEVER的值,而这个值在hibernate3.0似乎是不能理解的,当然就不行了,所以报错就要你修改session的模式.

解决方法:

方法一:就是继承OpenSessionInViewFilter类,然后重写这个方法,加句 this.setFlushMode(FlushMode.AUTO);或者干脆把session里面直接扔个FlushMode.AUTO,然后再重写一个叫closeSession的方法,记住一定要重写,因为增加了flushMode以后要调用session.flush()才可以正常提交数据,其实重写closeSession就是为了加1句session.flush(),然后下面调用super.closeSession()方法就行了。这种方法是我在网上找的一网友的解决方法,不过网上多不推荐这种方法
方法二:在spring配置文件里配置自己的事务
<!-- 配置事务的传播特性 ,指定事务管理器-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 配置详细的事务语义 -->
<tx:attributes>
<!-- methods starting with 'save', 'update' or 'remove' use the default transaction settings -->
<tx:method name="save*"/>
<tx:method name="update*"/>
<!-- other methods are set to read only -->
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>

<!-- 哪些类的哪些方法参与事务 -->
<aop:config proxy-target-class="true">
<!--配置切入点,匹配××包下所有的类的所有方法的执行-->
<aop:pointcut id="Operation"
expression="execution(* 包名.*DAO.*(..))"/>
<!-- 指定在txAdvice切入点应用txAdvice事务切面 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="Operation"/>
</aop:config>

这样的话,OpenSessionInViewFilter算是可以使用了,不用再每个many-to-one上加lazy了。不过OpenSessionInViewFilter还是有性能上的缺陷的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: