今天上午在用到hibernate的一对多的时候,出现了hibernate的延迟加载的异常,以前都是直接配对lazy=“false”,没有用过OpenSessionInViewFilter,只是晚上在宿舍和几位室友聊天的时候,听他们提过。就想用下,结果还真的出现了些许的问题,值得写篇文章来记录下。
首先自然是最web.xml中配置OpenSessionInViewFilter了,如下:没得说,网上一搜一堆的·······
这样的话还是不行,部署并启动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配置文件里配置自己的事务
这样的话,OpenSessionInViewFilter算是可以使用了,不用再每个many-to-one上加lazy了。不过OpenSessionInViewFilter还是有性能上的缺陷的。