FlushMode属性与transaction(spring注入的事务)
一、参见hibernate的api
http://tool.oschina.net/apidocs/apidoc?api=hibernate-3.6.10
http://tool.oschina.net/apidocs/apidoc?api=hibernate-4.1.4
说明:贴出两个版本的原因在于FlushMode属性在3.6与4.1版本的设置有所不同,3.6的FlushMode属性是一个Class类,而4.1已更换了Enum。
二、 FlushMode属性(策略)
在org.hibernate Class FlushMode中这样解释它的作用:Represents a flushing strategy. The flush process synchronizes database state with session state by detecting state changes and executing SQL statements.
代表一个flushing(刷新)的策略,它将通过改变session的状态和执行SQL的状态来处理线程中的数据。

AUTO: 在确保查询从不会返回脏数据的情况下,在查询前刷新Session。
MANUAL:Session永远只会在应用程序调用Session.flush()方法时才会刷新。
说明:
1. Session:Session接口是Hibernate向程序提供操纵数据库的最主要接口,是单线程对象,它提供了基本的保存、更新、删除和查询方法。它有一个缓存,保存了持久化对象,当清理缓存时,按照这些持久化对象同步更新数据库。根据Session的定义,可以知道刷新Session也就刷新了数据库。
2.调用Session.flush()方法,不管FlushMode被设置成任何策略,均会将刷新Session,使其中的缓存数据同步至数据库。
3.ALWAYS与AUTO的区别:从API看出,AUTO的解释Session刷新较ALWAYS多了一个“sometimes ”,说明AUTO并不会像ALWAYS那样总是刷新Session,那它在何时才会刷新呢?当hibernate缓存中的对象被改动之后,会被标记为脏数据(即与数据库不同步了)。当 session设置为FlushMode.AUTO时,hibernate在进行查询的时候会判断缓存中的数据是否为脏数据,是则刷数据库,不是则不刷,而always是直接刷新,不进行任何判断。很显然auto比always要高效得多。
4.设置FlushMode.MANUAL,在操作过程中hibernate会将事务设置为readonly,所以在增加、删除或修改操作过程中会出现如下错误:
| org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition. |
解决方式见“附:解决因FlushMode设置出现不能进行增、删、改的异常”
用表格形式表示如下:
表1
|
Session的刷新策略 |
|||
|
调用Session的查询方法时 |
调用Session.commit()时 |
调用Session.flush()时 |
|
|
刷新 |
刷新 |
刷新 |
|
|
当缓存被标记为脏数据时,刷新 |
刷新 |
刷新 |
|
|
不刷新 |
刷新 |
刷新 |
|
|
不刷新 |
不刷新 |
刷新 |
|
三、小结:FlushMode的4个属性实际上代表了Hibernate处理Session中的持久化对象的缓存的4种策略,这4种策略最大的不同就是刷新Session,将其中的缓存的持久化对象同步更新数据库的时间点不同。
四、OpenSessionInViewFilter的FlushMode属性设置与transaction(spring注入的事务)的关系:假设在OpenSessionInViewFilter设置FlushMode.MANUAL。若OpenSessionInViewFilter在getSession的时候,会把获取回来的session的flush mode 设为FlushMode.MANUAL。然后把该sessionFactory绑定到TransactionSynchronizationManager,使request的整个过程都使用同一个session,在请求过后再解除该sessionFactory的绑定,最后closeSessionIfNecessary根据该session是否已和transaction绑定来决定是否关闭session。在这个过程中,若HibernateTemplate 发现自当前session有不是readOnly的transaction,就会获取到FlushMode.AUTO Session,使方法拥有写权限。也即是,如果有不是readOnly的transaction就可以由Flush.NEVER转为Flush.AUTO,拥有insert,update,delete操作权限,如果没有transaction,并且没有另外人为地设flush model的话,则doFilter的整个过程都是Flush.MANUAL。所以受transaction保护的方法有写权限,没受保护的则没有。
附:解决因FlushMode设置出现不能进行增、删、改的异常
1.配置事务,spring会读取事务中的各种配置来覆盖hibernate的session中的FlushMode。此种情况下,即使在FlushMode设置MANUAL也没有关系(这并意味OpenSessionInViewFilter的FlushMode属性可以随意设置,这得依据实际需求,具体参见第四点--OpenSessionInViewFilter的FlushMode属性设置与transaction(spring注入的事务)的关系)。
例:
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<aop:config>
<aop:pointcut id="managerOperation"
expression="execution(* com.test.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="managerOperation" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" read-only="true" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" isolation="REPEATABLE_READ"/>
</tx:attributes>
</tx:advice>
2.直接修改opensessioninviewfilter过滤器的配置,配置过滤器的时候置 openSession org.springframework.orm.hibernate3.support.OpenSessionInViewFilter中 flushMode为AUTO/COMMIT 。注意:如果这样设置,则要么结合1,要么结合3,因为不管怎样,对于Hibernate来说总是要配置事务,否则无法操作持久化对象同步至数据库。
例:
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>flushMode</param-name>
<param-value>AUTO</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.先编程式修改FlushMode,比如session.setFlushMode(FlushMode.AUTO);
例:
@Override
public void saveOrUpdate(T t) {
Session session = null;
Transaction tr = null;
try {
session = HibernateSessionFactory.getSession();
tr = session.beginTransaction();
session.saveOrUpdate(t);
tr.commit();
HibernateSessionFactory.closeSesssion();
} catch (Exception e) {
e.printStackTrace();
tr.rollback();
}
}
鸣谢:http://blog.csdn.net/accpsz/article/details/6010618
http://blog.csdn.net/looyo/article/details/6309136
FlushMode属性与transaction(spring注入的事务)的更多相关文章
- spring 声明式事务原理解读
在Spring中,声明式事务是通过事务属性(transaction attribute)来定义的.事务属性描述了事务策略如何应用到方法上.事务属性包含5个方面: 传播行为 隔离级别 是否只 ...
- Spring注入JPA+JPA事务管理
本例实现的是Spring注入JPA 和 使用JPA事务管理.JPA是sun公司开发的一项新的规范标准.在本质上来说,JPA可以看作是Hibernate的一个子集:然而从功能上来说,Hibernate是 ...
- Spring 声明式事务,propagation属性列表及isolation(隔离级别)
Spring 声明式事务,propagation属性列表 TransactionDefinition接口中定义,共有7种选项可用: PROPAGATION_REQUIRED:支持当前事务,如果当前没有 ...
- SPRING事务的属性有哪些?其中,事务隔离级别有哪几种?什么情况需要使用这几种事务隔离级别?
Spring 声明式事务,propagation属性列表 PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. PROPAGATION_SU ...
- spring测试junit事务管理及spring面向接口注入和实现类单独注入(无实现接口),实现类实现接口而实现类单独注入否则会报错。
1.根据日志分析,spring junit默认是自动回滚,不对数据库做任何的操作. 18:16:57.648 [main] DEBUG o.s.j.d.DataSourceTransactionMan ...
- spring注入 属性注入 构造器注入 set方法注入
spring注入 属性注入 构造器注入 set方法注入(外部bean注入)
- 使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务。
使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务.
- Spring提取@Transactional事务注解的源码解析
声明:本文是自己在学习spring注解事务处理源代码时所留下的笔记: 难免有错误,敬请读者谅解!!! 1.事务注解标签 <tx:annotation-driven /> 2.tx 命名空间 ...
- JavaEE学习之Spring声明式事务
一.引言 上一篇文章,学习了AOP相关知识,并做了一个简单的Hello world.本文在上篇文章的基础上,进一步学习下Spring的声明式事务. 二.相关概念 1. 事务(Transaction)— ...
随机推荐
- spark集成hive遭遇mysql check失败的问题
问题: spark集成hive,启动spark-shell或者spark-sql的时候,报错: INFO MetaStoreDirectSql: MySQL check failed, assumin ...
- C语言sprintf与sscanf函数[总结]
sprintf函数 sprintf函数原型为 int sprintf(char *str, const char *format, ...).作用是格式化字符串,具体功能如下所示: (1)将数字变量转 ...
- 【转】Log4.NET mark
C#通过log4net进行异常记录 C#中异常的记录也有一个模板,就是log4net.多的就不说了直接看怎么用的吧. 1.引用log4net.dll. 2.实现log4net的方法. public c ...
- sql新手全套
--[数据库]gocreate database DB_MGG --添加数据库on(name=DB_MGG --逻辑名称,filename='C:\MDB\DB_MGG.mdf' --物理名称 逻 ...
- 实例介绍Cocos2d-x中Box2D物理引擎:碰撞检测
在Box2D中碰撞事件通过实现b2ContactListener类函数实现,b2ContactListener是Box2D提供的抽象类,它的抽象函数:virtual void BeginContact ...
- 关于FPGA(verilog)电平检测模块的易错点分析
reg F1,F2; // F2 Previous State, F1 Current State always@(posedge CLK or negedge RSTn) if(!RSTn) beg ...
- C++与Lua交互(五)
引言 要将C++中的对象类型映射到Lua中,就不得不要先了解Lua面向对象的机制.在这里,我们先看一下Lua面向对象的实现基础--metatable,再以此实现C++对象到Lua的映射. Lua面向对 ...
- HotSpot算法实现
1.枚举根节点 可作为GC Roots的节点主要在全局性的引用(例如常量或类静态属性)与执行上下文(例如栈帧中的本地变量表)中. 可达性分析对执行时间的敏感体现在GC停顿上,因为分析工作必须在能确保一 ...
- jQuery(function($){...})与(function($){...})(jQuery)知识点分享
写jQuery插件时一些经验分享一下. 一.推荐写法 jQuery(function($){ //coding }); 全写为 jQuery(document).ready(function($){ ...
- Iso8601 日期格式
unit Iso8601Unit; interface type TIso8601 = class(TObject) public class function DateTimeFromIso8601 ...