Hibernate中的分离、持久和瞬态对象是什么?

111

在Hibernate中,什么是脱离态(detached)、持久态(persistent)和瞬时态(transient)对象?请举例解释。


在session.close后,它不会删除所有在session范围内的持久化对象吗? - jmj
是的,每当您关闭一个会话时,对象的持久状态就会转换为Detached状态。 - Rachel
@Rachel 提供了一个很好的链接,其中包含代码,可以更深入地理解。 - Priyank Thakkar
5个回答

181

Hibernate认为,与Session无关的持久化类的new实例,在数据库中没有表示,并且没有标识符值,被视为短暂的

Person person = new Person();
person.setName("Foobar");
// person is in a transient state

持久化实例在数据库中具有表示,标识符值,并与 Session 相关联。您可以通过将瞬态实例与 Session 关联来使其 持久化

Long id = (Long) session.save(person);
// person is now in a persistent state

现在,如果我们close Hibernate Session,则持久化实例将变为detached实例:它不再与Session关联(但仍然可以被修改并重新附加到新的Session中)。

所有这些都在Hibernate文档的整个第10章“使用对象”中清楚地解释了,我上面只是简单阐述。绝对是必读的。


一个标识符值可能不是对象持久化的严格条件,因为我可以使用分配的标识符生成策略。 - Abhijeet Kashnia
除了关闭读取实例的会话之外,您还可以通过调用session.evict()来分离一个实例。这将使其不再由Hibernate管理(从而防止对实例的更改自动传播回数据库)。您可以通过session.update()将更改发送到数据库,并使用session.merge()重新附加它。 - Mooshu
1
我们很多时候不遵循框架提供的原始文档,有时这些文档本身就带有隐藏信息和适当的描述,只需要探索一下。唯一的问题是我们很难找到它 :) - Aman Gupta
1
一个持久化实例在数据库中有一个表示。在提交保存操作之前,持久化实体在数据库中没有表示。 - O.Badr
1
那么,分离和瞬态实体的区别在于是否存在ID?如果我创建一个带有分配ID的新实例,那么它在形式上是瞬态的,因为它尚未持久化,但无法与分离实体区分,因为它具有ID。对吗? - Ruslan Stelmachenko

12

Hibernate中的对象有以下几种状态:

瞬态 - 使用new操作符实例化的对象称为瞬态对象。

如果一个对象刚刚使用new操作符进行了实例化,并且没有与Hibernate Session相关联,那么它就是瞬态的。它在数据库中没有持久化表示,也没有分配标识值。如果应用程序不再持有引用,则瞬态实例将被垃圾收集器销毁。

持久态 - 具有数据库标识的对象称为持久对象。

持久实例在数据库中具有表示和标识值。它可能刚刚保存或加载;但是,它肯定在Session范围内。Hibernate将检测对持久状态下对象所做的任何更改,并在工作单元完成时将状态与数据库同步。

游离态 - 已经持久化的对象,但它的Session已关闭,称为游离实例。

游离实例可以在以后重新附加到一个新的Session上,使其再次成为持久实例。这个特性支持长时间运行的单位工作的编程模型,需要用户思考时间。我们称它们为应用程序事务,即从用户角度来看的工作单元。

http://webiwip.com/interview-questions-answers/hibernate-interview-questions/32012


9

让我从垃圾收集器的角度来解释。

hibernate有三种对象状态(或hibernate对象范围):

  1. 瞬态
  2. 持久态
  3. 游离态

最好通过代码示例来理解-

我们以一个POJO类作为学生对象为例->

Student student = new Student(); 

现在,这个学生对象处于瞬态状态


当我们将这个POJO对象附加到Hibernate会话中->

session.save(student);

现在这个POJO对象处于持久化状态。(垃圾收集器的角度- GC无法清除处于持久化状态的任何对象。因此我们可以说,持久化状态就像是POJO对象的临时存储。)
如果我们执行->
session.beginTransaction.commit();

那么POJO对象处于永久或数据库存储状态

(垃圾回收器的角度 - GC无法清除此对象,因为该POJO对象现在超出了JVM的范围,并存储在数据库中的表格形式中。因此,我们可以说这种数据库存储状态就像是POJO对象的永久存储)


如果我们执行 ->

session.evict(student); 

当POJO对象从持久状态转换为分离状态时,它将被清除或移除。因此,POJO对象处于分离状态

(垃圾收集器的角度- GC可以轻松地从JVM中清除分离状态的POJO对象)


3

以下是实体:

@Entity
public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)    
    private long id;

    // other fields and methods.
}

以下内容翻译自Hibernate 5.2文档(同时也包含了removed状态):

transient

the entity has just been instantiated and is not associated with a persistence context. It has no persistent representation in the database and typically no identifier value has been assigned (unless the assigned generator was used).

City city = new City();

managed, or persistent

the entity has an associated identifier and is associated with a persistence context. It may or may not physically exist in the database yet.

// city will be in a managed/persistent state and any changes to it, will be tracked by hibernate
// and reflected to the database when the persistence context is flushed.
session.save(city);

detached

the entity has an associated identifier, but is no longer associated with a persistence context (usually because the persistence context was closed or the instance was evicted from the context)

// city is in a detached state, Hibernate is no longer aware of the entity 
session.evict(city)

removed

the entity has an associated identifier and is associated with a persistence context, however it is scheduled for removal from the database.

session.remove(city);


Note: Hibernate API offers couples of methods to switch between entity states, and I think it's worth exploring a Hibernate Session class.


0

除了已经确定的正确答案之外,持久化、瞬态和游离状态只是Hibernate中对象的状态。

更准确地说,这三种状态实际上展示了Hibernate对象的变化以及会话生命周期的状态。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接