今天程序出现了
引用
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了
评论
davidcen 2008-06-24

<bean name="openSessionInViewInterceptor"
		class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
		<property name="sessionFactory">
			<ref bean="sessionFactory" />
		</property>
		<property name="flushMode" value="1"/>
		<property name="singleSession" value="true" />
	</bean>

just set flushMode value =1
byduke 2008-04-03
不知道你是故意的还是也没注意,重写完这个方法以后必须重写里面的close方法

protected void closeSession(SessionFactory sessionFactory,Session session){
session.flush();
super.closeSession(sessionFactory,session);
}
不然根本不能运行,楼主不厚道啊,这样容易误导人
发表评论

您还没有登录,请登录后发表评论

xly_971223
搜索本博客
博客分类
我的相册
C5b0e206-307c-3f61-aa60-9cfd71c61bb3-thumb
u=3528569133,1587051000&gp=38.jpg
共 2 张
最近加入圈子
存档
最新评论