Hibernate事务并发之深入理解

来源:互联网 发布:如何开网络直播公司 编辑:程序博客网 时间:2024/06/07 15:54

 

基于历史遗留原因和存储、查询的效率考虑,我觉得原先的关系型数据库短期内不大可能变成完全面向对象的,
 
而我们业务系统大多又在对象的基础上建模,对于这些系统,O/R映射是必须的,hibernate是O/R框架中的佼佼
 
者,hibernate能够成为jboss中持久层的实现就是一个不争的事实,对于利用struts-spring-hibernate
 
轻型框架构建的系统来说,hibernate无疑也是其中的攻坚部分。的确,在我接触struts、spring 甚至 ejb3.0中的部
分东西以后,始终觉得hibernate或者持久层的实现是关乎一个系统性能的最最关键。
 
我觉得hibernate的重点无外乎几个方面
 
(1) 关系型数据库记录到对象的映射(即数据库schema到java类的映射)
 
(2) 数据库表关联到java对象的映射(一对多,多对一,多对多,一对一等)
 
(3) 各种查询的使用
 
(4) 事务(JDBC事务与JTA事务)的理解
 
(5) 缓存
 
这其中估计是表关联映射和事务比较难理解,这里就谈点对事务的理解。
 
今天读了hibernate参考文档中3.2.0版本11.3.4(定制自动化版本行为)中的一段话,话是这样的:
 
遗留系统的数据库Schema通常是静态的,不可修改的。或者,其他应用程序也可能访问同一数据 库,
 
根本无法得知如何处理版本号,甚至时间戳。在以上的所有场景中,实现版本化不能依靠 数据库表的
 
某个特定列。在<class>的映射中设置 optimistic-lock="all"可以在没有版本或者时间戳属性映射的
况下实现 版本检查,此时Hibernate将比较一行记录的每个字段的状态。请注意,只有当Hibernate能
 
够比 较新旧状态的情况下,这种方式才能生效,也就是说, 你必须使用单个长生命周期Session模式,
 
而不能使用 session-per-request-with-detached-objects模式。
 
开始不太能理解,后来仔细琢磨,豁然开朗,可以这样理解:
 
(1) 一般来说,hibernate在乐观并发控制中使用版本号来检查更改冲突,这点很容易理解,对于R记录,可能有C1
和C2两个人在同时修改,为了使得C1的修改不覆盖C2的修改(反过来也一样),可以在R记录结构上扩展一个
version的字段,这样,如果C1的修改同步到数据库时发现R记录的版本号已经不低于C1中的版本号(表明C2已经修
改过R记录)了,
 
就表明C1的修改必须回滚。
 
(2) 既然需要版本号来检查事务并发中的冲突,这对于无法扩展schema的遗留系统来说当然不可行了。
 
(3) 用版本号来检查冲突限于数据库只被使用hibernate为持久层的应用程序访问。
 
(4) 由于(2)(3),可以提供optimistic-lock="all"来进行冲突检查,如果要同步一个对象的修改到数据库,可以
比较对象未修改之前与数据库的记录,如果相同,则表示对象的修改不是基于脏数据的(没有其他人同步修改该
记录),可以同步该修改,否则,需要回退事务。
 
(5) 上面这段话中最难理解的就是"只有当Hibernate能够比较新旧状态的情况下,这种方式才能生效,
 
也就是说, 你必须使用单个长生命周期Session模式,而不能使用
 
session-per-request-with-detached-objects模式"。这段话反映的一个意思就是长生命周期session模式
是可以比较新旧状态的,而session-per-request-with-datached-object是不能比较新旧状态的,为什么呢?原来
长生命周期session中的对象一直没有脱离一个session,由于session有缓存,所以对象修改之前的状态是存在的,
可以和数据库记录进行比较。而detached-objects在未发生修改前的状态一般与session无关,没有缓存,不得而
知,所以自然也无法与数据库记录比较了。
 
 
原创粉丝点击