Hibernate 会话中持久对象的状态

Posted

技术标签:

【中文标题】Hibernate 会话中持久对象的状态【英文标题】:State of a persistent object in a Hibernate session 【发布时间】:2012-06-26 11:28:52 【问题描述】:

我有一个关于 Hibernate 的可能非常简单的问题:

如果我有一个对象的持久化实例,并且其中一些对象的属性在同一个 Session 内进行了修改,这些更改对我来说也可见吗?

或者我必须refresh 对象才能获得它的当前状态?


我想扩展我的问题:如果这些更改不在同一个Session 内进行怎么办?如果它们是在Session 中制作的,由相同的SessionFactory 提供怎么办?

【问题讨论】:

【参考方案1】:

如果您有一个实体加载了两次或更多次(不管是使用Query.list() 还是Session.load()),那么您总是会得到相同的Java 对象实例。由于是同一个实例,因此无论您在何处使用此实例,都可以看到对该实例的每次修改,因此对于未持久化到数据库的修改也是如此(这是一定的危险)。

如果实体使用两个不同的会话加载两次(会话是否来自同一个 SessionFactory 无关紧要),那么您将获得 Java 类的两个实例。这两个实例是独立的。一个实例未获知另一实例中的修改。如果修改被持久化到数据库中,情况也不是这样。即使您再次加载实体并且它已经在会话缓存中,您也不会得到修改(例如:session1.load(entity); session2.save(entity); session1.load(entity); 然后session1 不会加载session2所做的更改,因为实体已经在缓存)。如果直接在程序外部使用 SQL 进行修改,情况也是如此。要加载修改,您必须 evict() 实例或使用新会话。在这种情况下,建议使用版本化列(使用<version> 子句映射的列)以避免修改丢失。

【讨论】:

另一个极端情况是merge:您可以拥有一个持久化实例,以及一个具有相同身份的非持久化(或分离?)实例,当您使用后者调用merge 时,它的任何变化都将在前者中变得可见。但是,非持久性实例本身并不持久,因此它不会显示任何未来的变化。正常使用是在合并后丢弃该实例并使用持久实例。【参考方案2】:

不需要刷新,除非它被分离,否则它将是可见的。

【讨论】:

以上是关于Hibernate 会话中持久对象的状态的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate→ 《Hibernate程序开发》教材大纲

Hibernate学习- 初识

在 Hibernate 中调用 merge() 方法

Hibernate 使用说明

Java对象在Hibernate持久化层的状态

Hibernate 持久化对象状态