【问题标题】:What are detached, persistent and transient objects in hibernate?什么是休眠中的分离、持久和瞬态对象?
【发布时间】:2011-02-04 03:34:37
【问题描述】:

什么是休眠中的分离、持久和瞬态对象?请举例说明。

【问题讨论】:

  • 在 session.close 时它不会删除所有在会话范围内持久存在的对象吗?
  • 是的,它会被移除,因此每当您关闭会话时,对象的持久状态就会转换为分离状态。
  • @Rachel 不错的链接,提供代码以加深理解

标签: java hibernate orm


【解决方案1】:

不与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,持久化实例将成为一个分离实例:它不再附加到Session (但仍然可以修改并在以后重新附加到新的Session)。

我只是在上面解释的 Hibernate 文档的整个 Chapter 10. Working with objects 中清楚地解释了所有这些。绝对值得一读。

【讨论】:

  • 一个标识符值可能不是一个对象要持久化的严格条件,因为我可以使用分配的标识符生成策略。
  • 除了关闭在实例中读取的会话之外,还可以通过调用 session.evict() 来分离实例。这使它不再由 Hibernate 管理(从而防止对实例的更改自动传播回数据库)。您可以通过 session.update() 将更改发送到数据库,并使用 session.merge() 重新附加它。
  • 我们很多时候不遵循框架提供的原始文档..有时它本身有隐藏的信息和适当的描述只需要探索。唯一的问题是我们不容易找到它:)
  • A persistent instance has a representation in the database 在提交保存操作之前,持久实体在数据库中没有表示。
  • 那么,分离实体和瞬时实体的区别是存在ID吗?如果我创建具有分配 id 的新实例,那么正式它是瞬态的,因为它还没有持久化,但不能与分离区分开,因为它有一个 ID。对吗?
【解决方案2】:

给定以下实体:

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

    // other fields and methods.
}

来自Hibernate 5.2 documentation(我还包括removed 状态):

瞬态

实体刚刚被实例化并且没有与 持久性上下文。它在 数据库,通常没有分配标识符值(除非 使用了分配的生成器)。

City city = new City();

托管或持久

实体具有关联的标识符并与 持久性上下文。它可能实际存在也可能不存在于 数据库。

// 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);

分离

实体具有关联标识符,但不再关联 具有持久性上下文(通常是因为持久性上下文 已关闭或实例已从上下文中逐出)

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

已移除

实体具有关联的标识符并与 持久性上下文,但是它计划从 数据库。

session.remove(city);


注意: Hibernate API 提供了几种在实体状态之间切换的方法,我认为值得探索Hibernate Session class。

【讨论】:

    【解决方案3】:

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

    hibernate有3种Object状态(或)hibernate的Object Scope-

    1. 瞬态状态
    2. 持久状态
    3. 分离状态

    用一个代码例子更好理解-

    让我们将 POJO 类视为学生对象->

    Student student = new Student(); 
    

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


    当我们将此 POJO 对象附加到休眠会话时->

    session.save(student);
    

    现在这个 POJO 对象处于持久状态。

    (垃圾收集器的观点- GC 无法清除任何处于持久状态的对象。 所以我们可以说持久状态就像 POJO 对象的临时存储)


    如果我们执行->

    session.beginTransaction.commit();
    

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

    (垃圾收集器的观点- GC 无法清除此对象,因为此 POJO 对象现在超出了 JVM 的范围并存储在 在数据库中形成表格。所以我们可以说这个数据库存储状态就像 POJO 对象的永久存储)


    如果我们执行->

    session.evict(student); 
    

    然后 POJO 对象被逐出或从持久状态移回分离状态。所以这个 POJO 对象的状态是分离状态。

    (垃圾收集器的观点-GC可以很容易地从JVM中清除分离状态的POJO对象)

    【讨论】:

      【解决方案4】:

      休眠中的对象有以下状态:

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

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

      持久性 - 具有与之关联的数据库标识的对象称为持久性对象。

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

      Detached - 一个分离的实例是一个已经持久化的对象,但是它的 Session 已经关闭了。

      一个分离的实例可以在稍后的时间点重新附加到一个新的会话,使其再次持久化。此功能为需要用户思考时间的长时间运行的工作单元启用了编程模型。我们称它们为应用事务,即从用户的角度来看的一个工作单元。

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

      【讨论】:

        【解决方案5】:

        除了已经确定的正确答案之外,持久性、瞬态、分离只是对象在休眠中的状态。

        更准确的说,这三个状态其实就是展示了hibernate对象的变化和session的生命周期状态

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-01
          • 1970-01-01
          • 2010-11-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多