Hibernate session FlushMode

Hibernate session FlushMode有五种属性: 

1、NEVEL:已经废弃了,被MANUAL取代了 
2 MANUAL: 
如果FlushMode是MANUAL或NEVEL,在操作过程中hibernate会将事务设置为readonly,所以在增加、删除或修改操作过程中会出现如下错误 
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove ‘readOnly‘ marker from transaction definition; 
解决办法:配置事务,spring会读取事务中的各种配置来覆盖hibernate的session中的FlushMode; 
3 AUTO 
设置成auto之后,当程序进行查询、提交事务或者调用session.flush()的时候,都会使缓存和数据库进行同步,也就是刷新数据库 
4 COMMIT 
提交事务或者session.flush()时,刷新数据库;查询不刷新 
5 ALWAYS: 
每次进行查询、提交事务、session.flush()的时候都会刷数据库 
ALWAYS和AUTO的区别:当hibernate缓存中的对象被改动之后,会被标记为脏数据(即与数据库不同步了)。当 session设置为FlushMode.AUTO时,hibernate在进行查询的时候会判断缓存中的数据是否为脏数据,是则刷数据库,不是则不刷,而always是直接刷新,不进行任何判断。很显然auto比always要高效得多。 

参见hibernate的api说明https://www.hibernate.org/hib_docs/v3/api/org/hibernate/FlushMode.html

(二)

spring 环境下做一个check*操作时,抛出异常

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.

 

后来发现,由于我在Action中调的方法名是checkXXXXX打头,而我的applicationContext.xml中的相关配置如下:

Xml代码 
  1. <bean id="transactionInterceptor"  
  2.         class="org.springframework.transaction.interceptor.TransactionInterceptor">  
  3.         <property name="transactionManager" ref="transactionManager" />  
  4.         <property name="transactionAttributes">  
  5.             <props>  
  6.                 <prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>  
  7.                 <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>  
  8.                 <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>  
  9.                 <prop key="view*">PROPAGATION_REQUIRED,readOnly</prop>                 
  10.                 <prop key="merge*">PROPAGATION_REQUIRED,readOnly</prop>  
  11.                 <prop key="check*">PROPAGATION_REQUIRED,readOnly</prop>  
  12.                 <prop key="insert*">  
  13.                     PROPAGATION_REQUIRED,-GenericException   
  14.                 </prop>  
Xml代码  
  1. <bean id="transactionInterceptor"  
  2.         class="org.springframework.transaction.interceptor.TransactionInterceptor">  
  3.         <property name="transactionManager" ref="transactionManager" />  
  4.         <property name="transactionAttributes">  
  5.             <props>  
  6.                 <prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>  
  7.                 <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>  
  8.                 <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>  
  9.                 <prop key="view*">PROPAGATION_REQUIRED,readOnly</prop>                
  10.                 <prop key="merge*">PROPAGATION_REQUIRED,readOnly</prop>  
  11.                 <prop key="check*">PROPAGATION_REQUIRED,readOnly</prop>  
  12.                 <prop key="insert*">  
  13.                     PROPAGATION_REQUIRED,-GenericException  
  14.                 </prop>  

 即check打头的操作时,是不可操作数据库的,包括更新与增加数据。

找到原因后将

Xml代码 
  1. <prop key="check*">PROPAGATION_REQUIRED,readOnly</prop>  
Xml代码  
  1. <prop key="check*">PROPAGATION_REQUIRED,readOnly</prop>  

 改为

Xml代码 
  1. <prop key="check*">PROPAGATION_REQUIRED</prop>  
Xml代码  
  1. <prop key="check*">PROPAGATION_REQUIRED</prop>  

 后,重启服务,问题解决。

 

(三)

<aop:config proxy-target-class="true">
  <aop:pointcut id="managerOperation" expression="execution(* com.yyii.eip..service.*Manager.*(..))"/>   
  <aop:advisor advice-ref="txAdvice" pointcut-ref="managerOperation"/>
  </aop:config>

<!-- 基本事务定义 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
  <tx:method name="save*"/>
  <tx:method name="update*"/>
  <tx:method name="remove*"/>
  <tx:method name="delete*"/>
  <tx:method name="create*"/>
  <!-- other methods are set to read only -->   
  <tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
如果把proxy-target-class="true"去掉, 不会报warn
但如果写上proxy-target-class="true", 2.0的配置依然会报WARN

 

修改web.xml中的]<param-value>false</param-value>为false试试!

<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>false</param-value> </init-param>
</filter>

 

 

<!-- 配置事务特性 -->   
  <tx:advice id="txAdvice" transaction-manager="transactionManager">
  <tx:attributes>
  <tx:method name="add*" propagation="REQUIRED"/>
  <tx:method name="del*" propagation="REQUIRED"/>
  <tx:method name="update*" propagation="REQUIRED"/>
  <tx:method name="*" read-only="true"/>
  </tx:attributes>
  </tx:advice>
  <!-- 配置那些类的方法进行事务管理 -->
  <aop:config>
  <aop:pointcut id="allManagerMethod" expression="execution (* com.landa.oa.manager.*.*(..))"/>
  <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod"/>
  </aop:config>

<!--End_rbody_54519835//-->

 

 Exceptions:

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:1112)
 at org.springframework.orm.hibernate3.HibernateTemplate$14.doInHibernate(HibernateTemplate.java:663)

 


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。