使用Spring提供的Open Session In View而引起Write operations are not allowed in read-only mode (FlushMode.NEVER) 错误解决:
在没有使用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(具体参看),功能相同,只是一个在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。
解决方案:
《一》我实践过,这个filter写在最前面 保险
在 web.xml配置里添加
<filter> <filter-name>OpenSessionInViewFilter</filter-name> <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter </filter-class> <init-param> <param-name>sessionFactoryBeanName</param-name> <param-value>sessionFactory</param-value> </init-param> <init-param> <param-name>singleSession</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name> flushMode </param-name> <param-value>AUTO </param-value> </init-param> </filter> 。。。。 <filter-mapping> <filter-name>OpenSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
《二》
般这个错误是事务引起的,如果确定事务没有问题,还是有这个错,可以重写OpenSessionInViewFilter的2个方法
在myfaces的wiki里提供了OpenSessionInViewFilter的一个子类如下:
public class OpenSessionInViewFilter extends org.springframework.orm.hibernate3.support.OpenSessionInViewFilter { /** * we do a different flushmode than in the codebase * here */ protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException { Session session = SessionFactoryUtils.getSession(sessionFactory, true); session.setFlushMode(FlushMode.COMMIT); return session; } /** * we do an explicit flush here just in case * we do not have an automated flush */ protected void closeSession(Session session, SessionFactory factory) { session.flush(); super.closeSession(session, factory); } }