`
chillwarmoon
  • 浏览: 153328 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Hibernate在应用层对并发事务的控制

阅读更多
Hibernate与事务处理一文中,介绍了事务以及并发事务处理时的问题,和针对于这些问题在数据库层所能做的隔离级别,但是在选择read commit和repeatable read两个隔离级别时,如果考虑到performance和scalability,可以选择一个折衷的方案,也就是在数据库中的隔离级别选择read commit,而通过对应用程序的控制,可以达到repeatable read的效果。Hibernate在程序中控制并发的事务处理上,也有自己的方法,本文在Hibernate与事务处理基础上,对Hibernate的这些并发事务处理方法进行介绍。
数据库隔离级别可以通过设置hibernate的属性文件,来改变数据库默认的隔离级别:
xml 代码
  1. 1:Read umcommited  
  2. 2:Read commited  
  3. 3:Repeatable read  
  4. 4:Serializable  

在这里设置hibernate.connection.isolation=2;但需要注意的是,如果hibernate用在了应用服务器上,该应用服务 器对数据库连接提供了受管理的控制,则这里设置的isolation级别失效,采用的是app server定义的级别,可以通过改变app server的配置来改变该隔离级别。
因为这里设置的隔离级别是read commit,那如果想达到repeatable read,则需要设置version number或者timestamp。

如果某个项目从头到尾开始设计和开发,考虑到事务处理,则在需要并发控制的数据库表字段上,添加和hibernate的version number相对应的字段。例如对Student表的并发控制,则需要在TSTUDENT表上添加STU_VERSION字段,在ORM的映射文件中需要在标识符属性下添加,例如:
java 代码
 
  1. <class name="Student" table="TSTUDENT">  
  2. ...  
  3. <!---->class>  

在Student.java的pojo文件中添加:
java 代码
 
  1. public class Student {  
  2. ....  
  3. private int version;  
  4. ...  
  5. }  

version属性是不能被应用所改变的,所以仅仅提供get方法即可。但是version number是怎样在应用层提供对事务的并发处理机制呢?原理是这样的:在hibernate的事务A(在这里假设事务的范围和Session范围一致,每个Session对应一个persistent context)中,执行每一个DML操作,都会先检查一下对象的version属性,假如从数据库中得到的student实例的version属性是1,此时student已经加载到Session对应的persistent context中,如果对student对象进行改变,在Session.flush()的时候,则将persistent context中的student对象的version属性设置为2,然后在保存student对象时,将对象对应的记录version字段更新为2。
注意的是,如果并发的另一个事务B在事务A进行保存操作之前,已经将version更新为2或者更高值的student存入数据库,那A在保存student之前,需要检查该persistent object对应的记录的version为1(因为在从数据库取得persistent object的时候,version为1)的行的个数,如果行数为0,则抛出 StaleObjectStateException,表明存在其他的事务更新了数据库,那这样的话,A事务的更新操作就不会覆盖B事务的更新操作,达到了避免(3)问题中的second lost update(见Hibernate与事务处理)。
当然避免了second lost update是不够的,因为是不是这样就能够具有repeatable read的隔离级别呢?比较一下read commit和repeatable read的隔离级别的差别,read commit是读事务允许其他事务并发执行,而repeatable read是读事务不允许写事务并发执行,在hibernate中,通过Session对应的persistent context来实现后者,具体是在一个事务A中(假设事务的范围和Session范围一致),读取student对象到persistent context,此时事务B更改了student对象对应的记录并进行持久化,根据数据库的默认隔离级别read commit,那么A事务如果再读取student对象,那就是产生unrepeatable read,其实不然,正是因为hibernate的persistent context,使得A事务再次读取student不是从数据库中读取,而是从当前的Session读取,因此避免了unrepeatable read,同时使得具有类似于数据库隔离级别repeatable read的隔离效果。

当然我们这里假设的是事务的范围和Session范围一致,但是当用户操作中途停留时间过长,则需要将不同的事务在同一conversation下实现,要保证不同事务共用Session可以通过Hibernate的FlushMode来实现。当然也可以保证Session和事务的对应,通过在不同Session中传递detached object来实现。

对于Hibernate在应用层对并发事务的控制方法还有timestamp,pessimistic locking,这里先不做介绍。
分享到:
评论
6 楼 xianyun 2007-07-14  
hibernate使用version可以来解决多个操作同时对数据进行更新的问题,它是通过程序的处理来实现的,是脱离事务的,或者事务级别很低,你要把事务设成repeatable read,反而不好用了(是吧)。它只是用来解决并发更新的问题,与事务隔离级别实现的功能是不完全一样的。
5 楼 chillwarmoon 2007-07-14  
如果有a、b两个对象,在第一个事务中先对a进行了读取,存到了它的缓存中。第二个事务对a、b对象都进行了更新,并提交了事务。然后在第一个事务再次对 a、b进行读取,它可不会知道a已经被其他事务修改了,读的还是缓存中的a,而b在缓存中没有,所以直接读数据库,因为事务是read commited,所以能读到被第二个事务修改的值,那么a、b两个对象的值一个被修改前的一个是被修改后的,是不一致的,可能会影响业务。<br/>
<br/>
你说的对,但是有没有其他方法用hibernate达到应用一层的repeatable read呢?如果使用数据库的repeatable read,那这样的话应用性能会降低。<br/>
如果没有这样的方法,那hibernate又是怎么样保证既不降低应用性能又能很好的处理并发事务呢?
4 楼 Godlikeme 2007-07-14  
对于hibernate在应用一层所作的并发处理是持怀疑态度的,
Lock_mode最终还是落在数据库的transaction上,不同数据库的支持不一样。

version这些处理,觉得只是一些小技巧,但在不同的数据库平台,不同的事务隔离级别体现出来的效果不一样。而且要在业务逻辑中写代码去做判断和处理。
3 楼 xianyun 2007-07-14  
chillwarmoon 写道
xianyun 写道
引用
使得具有类似于数据库隔离级别repeatable read的隔离效果


如果有两个相关的对象,一个在hibernate缓存中,一个不在,有另外一个事务对两个对象都进行的更新,并提交,那还能读到两个对象一致的状态吗?

这个问题就看hibernate的version number是怎么增加的,如果另外的事物对两个对象都进行更新,那么第一个事务所在的persistent context中的detached ojbect就是dirty data,如果第一个事务再次读关联对象时,如果被关联对象是lazy的,那么和数据库中的数据不一样,会产生异常,保证不读取两个不一致的状态。如果被关联对象不是lazy的,已经加载到persistent context中,那么第一个事物两次读取都从persistent context中读,应该是一致的。

你可以做个实验看看。


你怎么就不明白呢,如果有a、b两个对象,在第一个事务中先对a进行了读取,存到了它的缓存中。第二个事务对a、b对象都进行了更新,并提交了事务。然后在第一个事务再次对a、b进行读取,它可不会知道a已经被其他事务修改了,读的还是缓存中的a,而b在缓存中没有,所以直接读数据库,因为事务是read commited,所以能读到被第二个事务修改的值,那么a、b两个对象的值一个被修改前的一个是被修改后的,是不一致的,可能会影响业务。

如果事务级别是Repeatable read呢,不管第二个事务怎么修改数据,在第一个事务中后面读到a、b的值始终是第一次读取a当时时刻的值,也就是第二个事务修改前的值,a与b始终是一致的。

所以说hibernate能实现repeatable read的隔离效果这个说法是有问题的。

其实这和hibernate没有关系,即使在开始读取的时候,不可能一下全部把数据读出来,需要一个一个的读,在这期间也有可能后面的数据被其他事务修改了,导致和前面的不一致,所以,要实现Repeatable read的功能,还是要设置Repeatable read的事务隔离级别。
2 楼 chillwarmoon 2007-07-14  
xianyun 写道
引用
使得具有类似于数据库隔离级别repeatable read的隔离效果


如果有两个相关的对象,一个在hibernate缓存中,一个不在,有另外一个事务对两个对象都进行的更新,并提交,那还能读到两个对象一致的状态吗?

这个问题就看hibernate的version number是怎么增加的,如果另外的事物对两个对象都进行更新,那么第一个事务所在的persistent context中的detached ojbect就是dirty data,如果第一个事务再次读关联对象时,如果被关联对象是lazy的,那么和数据库中的数据不一样,会产生异常,保证不读取两个不一致的状态。如果被关联对象不是lazy的,已经加载到persistent context中,那么第一个事物两次读取都从persistent context中读,应该是一致的。

你可以做个实验看看。
1 楼 xianyun 2007-07-14  
引用
使得具有类似于数据库隔离级别repeatable read的隔离效果


如果有两个相关的对象,一个在hibernate缓存中,一个不在,有另外一个事务对两个对象都进行的更新,并提交,那还能读到两个对象一致的状态吗?


引用
而repeatable read是读事务不允许写事务并发执行
??

相关推荐

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

    第3章 第一个Hibernate应用  3.1 创建Hibernate的配置文件  3.2 创建持久化类  3.3 创建数据库Schema  3.4 创建对象-关系映射文件  3.4.1 映射文件的文档类型定义(DTD)  3.4.2 把Customer持久化类映射到...

    Hibernate实战(第2版 中文高清版)

     10.1.2 Hibernate应用程序中的事务   10.1.3 使用Java Persistence的事务   10.2 控制并发访问   10.2.1 理解数据库级并发   10.2.2 乐观并发控制   10.2.3 获得额外的隔离性保证   10.3 非事务数据...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

    第3章 第一个Hibernate应用  3.1 创建Hibernate的配置文件  3.2 创建持久化类  3.3 创建数据库Schema  3.4 创建对象-关系映射文件  3.4.1 映射文件的文档类型定义(DTD)  3.4.2 把Customer持久化类映射到...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

    第3章 第一个Hibernate应用  3.1 创建Hibernate的配置文件  3.2 创建持久化类  3.3 创建数据库Schema  3.4 创建对象-关系映射文件  3.4.1 映射文件的文档类型定义(DTD)  3.4.2 把Customer持久化类映射到...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

    第3章 第一个Hibernate应用  3.1 创建Hibernate的配置文件  3.2 创建持久化类  3.3 创建数据库Schema  3.4 创建对象-关系映射文件  3.4.1 映射文件的文档类型定义(DTD)  3.4.2 把Customer持久化类映射到...

    hibernate 教程

    乐观并发控制(Optimistic concurrency control) 10.4.1. 使用长生命周期带有自动版本化的会话 10.4.2. 使用带有自动版本化的多个会话 10.4.3. 应用程序自己进行版本检查 10.5. 会话断开连接(Session...

    hibernate

    乐观并发控制(Optimistic concurrency control) 10.4.1. 使用长生命周期带有自动版本化的会话 10.4.2. 使用带有自动版本化的多个会话 10.4.3. 应用程序自己进行版本检查 10.5. 会话断开连接(Session...

    低清版 大型门户网站是这样炼成的.pdf

    5.9 hibernate应用的性能优化 336 5.10 多数据源的应用 338 5.11 jdbc的应用 343 5.12 hibernate调用存储过程 343 5.13 xml数据持久化 346 5.14 小结 348 第6章 充分利用spring 2.5的ioc利器统管bean世界 349 ...

    Spring3.x企业应用开发实战(完整版) part1

     《Spring3.x企业应用开发实战》是在《精通Spring2.x——企业应用开发详解》的基础上,经过历时一年的重大调整改版而成的,本书延续了上一版本追求深度,注重原理,不停留在技术表面的写作风格,力求使读者在熟练...

    Spring.3.x企业应用开发实战(完整版).part2

     《Spring3.x企业应用开发实战》是在《精通Spring2.x——企业应用开发详解》的基础上,经过历时一年的重大调整改版而成的,本书延续了上一版本追求深度,注重原理,不停留在技术表面的写作风格,力求使读者在熟练...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    该案例采用目前最流行、最规范的java ee架构,整个应用分为jpa实体层、eao层、业务逻辑层、mvc层和视图层,各层之间分层清晰,层与层之间以松耦合的方法组织在一起。该案例既提供了ide无关的、基于ant管理的项目源码...

    java面试题

    答:声明式的事务管理主要是将在进行对数据库中数据的添加或者修改时需要执行事务管理,主要是为了避免在执行添加或修改的时候添加或修改不完全正确,导致数据丢失。spring使用AOP面向切面的思想进行事务管理的。 ...

    基于J2EE框架的个人博客系统项目毕业设计论文(源码和论文)

    由于B/S架构管理软件只安装在服务器端(Server)上,即应用程序在部署、升级、维护时,只需要在服务器端进行配置就可以了,网络管理人员只需要管理服务器就行了,用户界面主要事务逻辑在服务器(Server)端完全通过...

    从J2SE到J2EE知识点介绍

    5. Hibernate的事务与并发 238 (十) 数据库 240 1. 数据库的基本概念 240 2. 数据模型 240 3. 关系模型 241 数据流图(Data Flow Diagram,DFD) 241 E-R图 241 4. 关系规范化 242 5. Mysql 的安装 243 6. Transact-SQL...

    iBATIS实战

    7.6.3 将事务在业务逻辑层划界 128 7.7 小结 129 第8章 使用动态SQL 130 8.1 处理动态WHERE子句条件 130 8.2 熟悉动态标签 132 8.2.1 dynamic标签 134 8.2.2 二元标签 135 8.2.3 一元标签 136 8.2.4 参数标签 137 ...

    基于J2EE框架的个人博客系统项目毕业设计论...

    由于B/S架构管理软件只安装在服务器端(Server)上,即应用程序在部署、升级、维护时,只需要在服务器端进行配置就可以了,网络管理人员只需要管理服务器就行了,用户界面主要事务逻辑在服务器(Server)端完全通过...

    Java常见面试题208道.docx

    123.在 hibernate 中 getCurrentSession 和 openSession 的区别是什么? 124.hibernate 实体类必须要有无参构造函数吗?为什么? 十三、Mybatis 125.mybatis 中 #{}和 ${}的区别是什么? 126.mybatis 有几种分页方式...

    JAVA上百实例源码以及开源项目

     关于数字签名:产生RSA密钥对(myKeyPair),得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥...

    java开源包1

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

Global site tag (gtag.js) - Google Analytics