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代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
  3. <beans>  
  4.      <!-- Transaction template for Managers, from:   
  5.          http://blog.exis.com/colin/archives/2004/07/31/concise-transaction-definitions-spring-11/ -->  
  6.     <bean id="txProxyTemplate" abstract="true"   
  7.         class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">  
  8.         <property name="transactionManager">  
  9.             <!--org.springframework.orm.hibernate3.HibernateTransactionManager的Bean实例-->  
  10.             <ref bean="gkgltransactionManager" />  
  11.         </property>  
  12.         <property name="transactionAttributes">  
  13.             <props>  
  14.                 <prop key="save*">PROPAGATION_REQUIRED</prop>  
  15.                 <prop key="remove*">PROPAGATION_REQUIRED</prop>  
  16.                 <prop key="do*">PROPAGATION_SUPPORTS</prop>   
  17.                 <prop key="auto*">PROPAGATION_SUPPORTS</prop>  
  18.                 <!--对于其它方法要求事务并且是只读的-->  
  19.                 <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>  
  20.             </props>  
  21.         </property>  
  22.     </bean>  
  23.     <!-- Generic manager that can be used to do basic CRUD operations on any objects -->  
  24.     <bean id="manager" parent="txProxyTemplate">  
  25.         <property name="target">  
  26.             <bean class="com.neuqsoft.base.service.impl.BaseManager">  
  27.                 <property name="dao">  
  28.                     <ref bean="gkgldao" />  
  29.                 </property>  
  30.             </bean>  
  31.         </property>  
  32.     </bean>  
  33. </beans>  

对于清除readOnly标记是很简单的,只需把上述配置文件中txProxyTemplate Bean定义中的<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>中的readOnly及其前面的逗号去掉即可。

接下来我们讨论把Session改成FlushMode.COMMIT/AUTO,下面是HibernateTemplate中checkWriteOperationAllowed方法的源码:

Java代码
  1. protected void checkWriteOperationAllowed(Session session) throws InvalidDataAccessApiUsageException {   
  2.         if (isCheckWriteOperations() && getFlushMode() != FLUSH_EAGER &&   
  3.                  session.getFlushMode().lessThan(FlushMode.COMMIT)) {   
  4.             throw new InvalidDataAccessApiUsageException(   
  5.                     "Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): "+   
  6.                     "Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.");   
  7.          }   
  8.      }  
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代码
  1. HibernateTemplate tmp=getHibernateTemplate();      
  2. tmp.setFlushMode(HibernateTemplate.FLUSH_EAGER);   
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值