spring中OpenSessionInViewFilter的配置顺序问题

今天程序出现了
引用
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.

实际上这个问题不是第一次出现了 只是一直没有时间来研究它。今天得闲随即打开了OpenSessionInViewFilter这个文件。 首先先看一下我的web.xml配置
<!-- openSessionInView -->
	<filter>
		<filter-name>openSessionInView</filter-name>
		<filter-class>
			org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
		</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>openSessionInView</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
	<!--==================== rewriteFilter ====================-->

	<!--==================== Spring ApplicationContext ====================-->
	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			classpath*:com/redgateonline/showradio/resource/spring/applicationContext*.xml
		</param-value>
	</context-param>

	<!-- ==================== Webwork =================== -->

之前一直怀疑是filter配置的顺序问题 ,有几次修改了配置文件后问题就解决了。
先来看看OpenSessionInViewFilter中的doFilterInternal()方法,这里只给出关键部分,
//从servletContext中取sessionFactory
SessionFactory sessionFactory = lookupSessionFactory(request);
		boolean participate = false;

		if (isSingleSession()) {
			// single session mode
			if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
				// Do not modify the Session: just set the participate flag.
				participate = true;
			}
			else {
				logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");
				
Session session = getSession(sessionFactory); //通过sessionFactory获取session,这个session被绑定到当前线程中 在整个request期间使用
				TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
			}
		}
		else {
			// deferred close mode
			if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
				// Do not modify deferred close: just set the participate flag.
				participate = true;
			}
			else {
				SessionFactoryUtils.initDeferredClose(sessionFactory);
			}
		}


看看Session session = getSession(sessionFactory);中的getSession(sessionFactory)是怎么实现的
protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
		Session session = SessionFactoryUtils.getSession(sessionFactory, true);
		FlushMode flushMode = getFlushMode();
		if (flushMode != null) {
			session.setFlushMode(flushMode);
		}
		return session;
	}

OpenSessionInViewFilter有一个变量flushMode,可通过getter setter为其赋值,而其默认值为FlushMode.NEVER,这儿的NEVER值已经被deprecate了。
原来是这儿在捣鬼,只要写了子类覆盖setFlushMode(FlushMode.auto);就ok了

你可能感兴趣的:(DAO,spring,Hibernate,Web,Webwork)