Hibernate事务并发之深入理解
2007-12-30 21:28
821 查看
基于历史遗留原因和存储、查询的效率考虑,我觉得原先的关系型数据库短期内不大可能变成完全面向对象的,
而我们业务系统大多又在对象的基础上建模,对于这些系统,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通常是静态的,不可修改的。或者,其他应用程序也可能访问同一数据 库,
根本无法得知如何处理版本号,甚至时间戳。在以上的所有场景中,实现版本化不能依靠 数据库表的
某个特定列。在
情况下实现 版本检查,此时Hibernate将比较一行记录的每个字段的状态。请注意,只有当Hibernate能
够比 较新旧状态的情况下,这种方式才能生效,也就是说, 你必须使用单个长生命周期
而不能使用 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-per-request-with-detached-objects模式"。这段话反映的一个意思就是长生命周期session模式
是可以比较新旧状态的,而session-per-request-with-datached-object是不能比较新旧状态的,为什么呢?原来
长生命周期session中的对象一直没有脱离一个session,由于session有缓存,所以对象修改之前的状态是存在的,
可以和数据库记录进行比较。而detached-objects在未发生修改前的状态一般与session无关,没有缓存,不得而
知,所以自然也无法与数据库记录比较了。
而我们业务系统大多又在对象的基础上建模,对于这些系统,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模式,[b]而不能使用 [/b]
session-per-request-with-detached-objects模式"。这段话反映的一个意思就是长生命周期session模式
是可以比较新旧状态的,而session-per-request-with-datached-object是不能比较新旧状态的,为什么呢?原来
长生命周期session中的对象一直没有脱离一个session,由于session有缓存,所以对象修改之前的状态是存在的,
可以和数据库记录进行比较。而detached-objects在未发生修改前的状态一般与session无关,没有缓存,不得而
知,所以自然也无法与数据库记录比较了。
相关文章推荐
- 深入理解Mysql——锁、事务与并发控制
- [置顶] 深入理解Mysql——锁、事务与并发控制
- 深入理解Mysql——锁、事务与并发控制
- 设计----【分布式事务】深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解MySQL的并发控制、锁和事务【转】
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解Mysql——锁、事务与并发控制(辟谣)
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解分布式事务,高并发下分布式事务的解决方案