没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
Hibernate In Action
中文版
Java 爱好者 http://www.JavaFan.NET 制作
第四章 操作持久对象
4.1 持久化生命周期
由于 Hibernate 是透明的持久化机制—类不能意识到它们自己的持久能力—编写应用逻
辑时不用意识到你所操纵的对象是持久状态还是存在于内存中的临时状态。当应用调用对象
的方法时不需要关心它的状态是否是持久的。
然而,在持久状态的应用中,只要应用需要把内存中的状态传到数据库(反之亦然)就
必须同持久层打交道。你可以调用 Hibernate 持久化管理器和查询接口来完成这种操作。当
使用那种方式同持久层打交道时,应用关心与持久化相关的对象的状态及生命周期是必要的。
我们将把它称为持久化生命周期。
对于持久化生命周期,不同的 ORM 实现使用不同的术语,定义不同的状态及状态转换。
此外,内部使用的对象状态可能与其暴露给客户端应用的状态不同。Hibernate 仅仅定义了三
种状态:瞬时、持久和分离,对客户端代码隐藏了其内部实现的复杂性。这一章,我们解释
这三种状态:瞬时、持久和分离。
让我们在状态图中看看这些状态和它们的转换,如图 4.1 所示。你也可以看到调用持久
管理器触发转换的方法。在这一节我们讨论这张图;以后你无论什么时候需要一个综述都可
以引用它。
在其生命周期中,对象可以从瞬时对象转换到持久对象,再转换到分离对象。让我们仔
细看看这些状态中的每一个状态。
Hibernate In Action
中文版
Java 爱好者 http://www.JavaFan.NET 制作
图 4.1Hibernate 中的对象状态及转换
4.1.1 瞬时对象
在 Hibernate 中,使用 new 操作符初始化的对象不是立刻就是持久的。它们的状态是瞬时
的,也就是说它们没有跟任何数据库表的行相关联,只要应用不再引用这些对象(不再被任
何其它对象所引用),它们的状态将会丢失。这时,那些对象的生命期将会有效地终止,变得
不可访问,交给垃圾回收机制来回收。
Hibernate 认为所有的瞬时实例都是非事务的,瞬时实例状态的修改不能在任何事务的上
下文中执行。这就意味着 Hibernate 不能对瞬时对象提供任何回滚功能。(实际上 Hibernate 不
回滚任何对象所做的修改,以后你就会看到)。
默认地,仅仅被其他瞬时实例引用的对象也是瞬时的。把实例从瞬时状态转换为持久状
态有两种方式:调用持久管理器的 save()方法或者从已经存在的持久实例中创建引用。
Hibernate In Action
中文版
Java 爱好者 http://www.JavaFan.NET 制作
4.1.2 持久对象
持久实例是任何具有数据库标识的实例,就像第三章第 3.4 节“理解对象标识符”所定义
的那样。也就是持久实例有一个主键值设为数据库标识符。
持久实例可能是由应用程序初始化的对象调用持久管理器(Hibernate Session,本章的后
面部分将会详细讨论)的 save()方法实现持久化。然后,持久实例就跟持久管理器关联起来。
它们甚至可能是引用另一个已经与持久管理器相关联的持久对象来实现持久化。可选的,持
久实例可能是通过执行查询,通过标识符查找从数据库中检索出来的实例,或者是从另一个
持久实例开始导航对象图。换句话说,持久实例通常是同 Session 相关的,是事务的。
持久实例是在事务中进行操作的—它们的状态在事务结束时同数据库进行同步。当事务
提交时,通过执行 SQL 的 INSERT、UPDATE 和 DELETE 语句把内存中的状态同步到数据库
中。这个过程也可能在其它时间发生。例如,Hibernate 在执行查询之前可能要同数据库同步。
这就确保查询能够意识到在事务早期所做的更改。
我们称已经分配主键值但是还没有插入到数据库中的持久实例是新的。新的持久实例将
会仍然保持“新”的状态直到同步发生。
当然,你不必在事务结束时把内存中的每个持久对象的状态更新到数据库中对应的行上。
ORM 软件必须有一种机制来检测哪个持久对象已经被应用程序在事务中修改了。我们称其为
自动脏数据检查(修改过的对象还没有同步到数据库中被任为是脏的)。这种状态对于应用程
序来说是不可见的。我们把这种特性称为 transparent transaction-level write-behind
,
意思是
Hibernate 尽可能晚地把改变的状态同步到数据库中,但是对应用程序隐藏其实现细节。
Hibernate 能够确切地知道哪个属性改变了,因此可以在 SQL UPDATE 语句中仅包含那些
需要更新的列。这样做可以提高性能,对于一些特定的数据库尤其如此。然而,这样做并不
是总能得到性能提升,理论上,在 某 些 环境中,可能要降低一些性能。因此,Hibernate 在 SQL
UPDATE 语句中默认包含所有的列(因此,Hibernate 在启动时能够生成这个基本的 SQL,而
不是在运行时)。如果仅仅希望更新修改过的列,你可以在类映射中通过把 dynamic-update 设
Hibernate In Action
中文版
Java 爱好者 http://www.JavaFan.NET 制作
为 true 启动动态 SQL生成功能。(注意,此特性在手工编码的持久层中是非常难以实现的。)
下一章,我们详细讨论 Hibernate 的事务概念和同步过程(即 flushing)。
最后,持久实例通过调用持久管理器 API 的 delete()方法使其变成瞬时的,导致删除数据
库中相应的行。
4.1.3 分离对象
当事务结束时,同持久管理器相关联的持久实例仍然存在(如果事务成功,它们在内存
中的状态将会同数据库同步)。在具有过程范围标识(process-scoped identity
,
看下一节)的
ORM 解决方案中,这些实例保留着同持久管理器的关联并且仍然认为是持久的。
可是在 Hibernate 中,当你关闭 Session 时这些实例就失去了同持久管理器的关联。我们
把这些对象称为分离的,表明这些状态不再跟数据库中的状态同步,不再在 Hibernate 的管理
下。然而,它们仍然含有持久数据(可能是稳定的)。应用程序可能(通常)含有事务(及持
久管理器)之外的分离对象的引用。Hibernate 可以让你同新的持久管理器重新关联这些实例
以便在新事务中重用这些实例(重新关联后,这些对象被认为是持久的)。这种特性对怎样设
计多层应用有很大影响。从一个事务中返回对象到表示层,以后在新的事务中重用它们的能
力是 Hibernate 的一个主要卖点。我们在下一章讨论这种作为对于长时间运行的应用事务
(
application transaction
)的一种实现技术的使用方法。我们也在第八章“重新考虑传输对象”
这一节告诉你怎样通过使用分离的对象避免 DTO(anti-)模式。
Hibernate 也提供了一个显式的分离操作:Session 的 evict()方法。然而,这个方法只在 cache
管理中使用(考虑性能问题)。通常不显式地执行分离。然而,所有在事务中检索出来的对象
在当 Session 关闭或当它们被序列化时(例如,它们被远程传递)就 变 成分离的。因此,Hibernate
不需要提供控制子图分离的功能。然而,应用程序能够使用查询语言或显式的图表导航来控
制抓取子图(当前装载在内存中的实例)的深度。那么,当 Session 关闭时,整个子图(所有
与持久管理器关联的对象)就会变成分离的。
让我们再来看看不同的状态,但是这次考虑对象标识的范围。
剩余37页未读,继续阅读
bonze1023
- 粉丝: 2
- 资源: 39
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
前往页