spring hibernate 事务管理
2009-05-19 15:40
447 查看
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代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- Transaction template for Managers, from:
http://blog.exis.com/colin/archives/2004/07/31/concise-transaction-definitions-spring-11/ -->
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<!--org.springframework.orm.hibernate3.HibernateTransactionManager的Bean实例-->
<ref bean="gkgltransactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="do*">PROPAGATION_SUPPORTS</prop>
<prop key="auto*">PROPAGATION_SUPPORTS</prop>
<!--对于其它方法要求事务并且是只读的-->
<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</bean>
<!-- Generic manager that can be used to do basic CRUD operations on any objects -->
<bean id="manager" parent="txProxyTemplate">
<property name="target">
<bean class="com.neuqsoft.base.service.impl.BaseManager">
<property name="dao">
<ref bean="gkgldao" />
</property>
</bean>
</property>
</bean>
</beans>
对于清除readOnly标记是很简单的,只需把上述配置文件中txProxyTemplate Bean定义中的<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>中的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.");
}
}
通过阅读这段代码我们不难看出,在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);
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代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- Transaction template for Managers, from:
http://blog.exis.com/colin/archives/2004/07/31/concise-transaction-definitions-spring-11/ -->
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<!--org.springframework.orm.hibernate3.HibernateTransactionManager的Bean实例-->
<ref bean="gkgltransactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="do*">PROPAGATION_SUPPORTS</prop>
<prop key="auto*">PROPAGATION_SUPPORTS</prop>
<!--对于其它方法要求事务并且是只读的-->
<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</bean>
<!-- Generic manager that can be used to do basic CRUD operations on any objects -->
<bean id="manager" parent="txProxyTemplate">
<property name="target">
<bean class="com.neuqsoft.base.service.impl.BaseManager">
<property name="dao">
<ref bean="gkgldao" />
</property>
</bean>
</property>
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!-- Transaction template for Managers, from: http://blog.exis.com/colin/archives/2004/07/31/concise-transaction-definitions-spring-11/ --> <bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <!--org.springframework.orm.hibernate3.HibernateTransactionManager的Bean实例--> <ref bean="gkgltransactionManager" /> </property> <property name="transactionAttributes"> <props> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="remove*">PROPAGATION_REQUIRED</prop> <prop key="do*">PROPAGATION_SUPPORTS</prop> <prop key="auto*">PROPAGATION_SUPPORTS</prop> <!--对于其它方法要求事务并且是只读的--> <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop> </props> </property> </bean> <!-- Generic manager that can be used to do basic CRUD operations on any objects --> <bean id="manager" parent="txProxyTemplate"> <property name="target"> <bean class="com.neuqsoft.base.service.impl.BaseManager"> <property name="dao"> <ref bean="gkgldao" /> </property> </bean> </property> </bean> </beans>
对于清除readOnly标记是很简单的,只需把上述配置文件中txProxyTemplate Bean定义中的<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>中的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);
相关文章推荐
- Spring和Hibernate整合时对session及事务管理的理解
- Spring整合hibernate4:事务管理
- Hibernate将SessionFactory交给Spring来管理/Spring管理Hibernate事务的方式
- spring管理hibernate事务
- Spring中的事务管理,hibernate整合,struts整合(佟刚)
- hibernate,spring管理事务中(transaction,JDBC connection,Hibernate Session的使用)
- Spring整合Hibernate 声明式的事务管理
- spring和hibernate整合,事务管理
- Spring和Hibernate集成配置事务管理
- Spring整合Hibernate:2、使用Annotation方式进行声明式的事务管理
- Spring对Hibernate事务的管理
- Spring整合hibernate4:事务管理
- Spring中事务管理与Hibernate自带事务管理冲突的一个问题
- 关于spring hibernate的事务管理
- 使用spring管理hibernate的事务
- Hibernate与Spring的事务管理
- Spring管理 hibernate 事务配置的五种方式
- spring mvc + hibernate 事务管理 + mysql
- spring mvc+hibernate 实现事务管理(配置文件版)
- hibernate添加spring 事务管理注意问题记录