Write operations are not allowed in read-only mode

来源:百度文库 编辑:神马文学网 时间:2024/04/26 05:06:52
关键字: spring hibernate 事务管理HibernateDaoSupport的子类在保存实体时抛出InvalidDataAccessApiUsageException异常,异常堆栈如下:
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.
at org.springframework.orm.hibernate3.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1090)
at org.springframework.orm.hibernate3.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:629)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:367)
at org.springframework.orm.hibernate3.HibernateTemplate.save(HibernateTemplate.java:627)
在网上搜了一下,其中大多数文章又是提OpenSessionInViewFilter又是提OpenSessionInViewInterceptor的,大多云山雾罩、不知所云。
其实这个异常的提示还是很明确的:在只读模式下(FlushMode.NEVER/MANUAL)写操作不被允许:把你的Session改成FlushMode.COMMIT/AUTO或者清除事务定义中的readOnly标记。
首先看一下我Spring的配置文件,为了减少篇幅,仅将与事务有关的一部分贴在下面:
Xml代码




class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">






PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_SUPPORTS
PROPAGATION_SUPPORTS

PROPAGATION_SUPPORTS,readOnly














PROPAGATION_REQUIREDPROPAGATION_REQUIREDPROPAGATION_SUPPORTSPROPAGATION_SUPPORTSPROPAGATION_SUPPORTS,readOnly  对于清除readOnly标记是很简单的,只需把上述配置文件中txProxyTemplate Bean定义中的PROPAGATION_SUPPORTS,readOnly中的readOnly及其前面的逗号去掉即可。
接下来我们讨论把Session改成FlushMode.COMMIT/AUTO,下面是HibernateTemplate中checkWriteOperationAllowed方法的源码:
Java代码
protected void checkWriteOperationAllowed(Session session) throws InvalidDataAccessApiUsageException {
if (isCheckWriteOperations() && getFlushMode() != FLUSH_EAGER &&
session.getFlushMode().lessThan(FlushMode.COMMIT)) {
throw new 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.");
}
}
protected void checkWriteOperationAllowed(Session session) throws InvalidDataAccessApiUsageException {if (isCheckWriteOperations() && getFlushMode() != FLUSH_EAGER &&session.getFlushMode().lessThan(FlushMode.COMMIT)) {throw new 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.");}} 通过阅读这段代码我们不难看出,在Java代码中调用HibernateTemplate的save或者saveOrUpdate等涉及到写操作的方法之前需要把Session的刷新模式设置为FlushMode.COMMIT或更高的级别,或者把HibernateTemplate的刷新模式设置为FLUSH_EAGER,由于我们的Dao继承自HibernateDaoSupport,所以设置Session刷新模式的语句如下:getSession().setFlushMode(FlushMode.COMMIT);
而设置HibernateTemplate刷新模式的语句如下:
Java代码
HibernateTemplate tmp=getHibernateTemplate();
tmp.setFlushMode(HibernateTemplate.FLUSH_EAGER);
HibernateTemplate tmp=getHibernateTemplate();tmp.setFlushMode(HibernateTemplate.FLUSH_EAGER);  只要在调用HibernateTemplate涉及到写操作的方法之前正确设置了HibernateTemplate或者Session的刷新模式,则上述异常不会再抛出。