Hibernate -- 持久化对象的三种状态

持久化对象三种状态的概述

Hiberante 为了更好的来管理持久化类,特将持久化类分成了三种状态。在 Hibernate 中持久化的对象可以划分为三种状态,分别是瞬时态、持久态和脱管态,一个持久化了的实例可能处于三种不同状态中的某一种,三种状态的详细介绍如下。

  • transient 瞬时态
    瞬时态也称为临时态或*态,瞬时态的实例是由 new 命令创建、开辟内存空间的对象,不存在持久化标识 OID(相当于主键值),尚未与 Hibernate Session 关联,在数据库中也没有记录,失去引用后将被 JVM 回收。瞬时状态的对象在内存中是孤立存在的,与数据库中的数据无任何关联,仅是一个信息携带的载体。
  • persistent 持久态
    持久态的对象存在持久化标识 OID,加入到了 Session 缓存中,并且相关联的 Session 没有关闭,在数据库中由对应的记录,每条记录只对应唯一的持久化对象,需要注意的是,持久态对象是在事务还未提交前变持久态的。
  • detached 脱管态
    脱管态也称为离线态或游离态,当某个持久化状态的实例与 Session 的关联被关闭时就变成了脱管态。脱管态对象存在持久化标识 OID,并且仍然与数据库中的数据存在关联,只是失去了与当前 Session 的关联,脱管状态对象发生改变时 Hibernate 不能检测到。

Hibernate 持久化对象的三种状态转换

Hibernate -- 持久化对象的三种状态
当一个对象被执行 new 关键字创建后,该对象处于瞬时态;当对瞬时态对象执行Session#save()Session#saveOrUpdate()方法后,该对象被放入Session的一级缓存,对象进入持久态;当对持久态对象执行evict()close()clear()操作后,对象进入脱管态;当直接执行Session#get()Session#load()Session#find()Session#iterate()等方法从数据库里查询对象时,查询到的对象也处于持久态;当对数据库中的记录进行Session#update()Session#saveOrUpdate()以及Session#lock()等操作后,此时脱管态的对象就过渡到持久态;由于瞬时态和脱管态的对象不在Session的管理范围,所以会再一段时间后被 JVM 回收。
持久化对象的三种状态可以通过调用Session中的一系列方法实现状态间的转换,具体如下:

瞬时态转换到其他状态

瞬时态看的对象由 new 关键字创建,瞬时态对象转换到其他状态总结如下:

  • 瞬时态转换为持久态:执行Session#save()Session#saveOrUpdate()方法。
  • 瞬时态转换为脱管态:为瞬时态对象设置持久化标识 OID。

持久态对象转换到其他状态

持久化对象额可以直接通过 Hibernate 中Session#get()Session#load()方法,或者 Query 查询从数据库中获得,持久态对象转换到其他状态总结如下:

  • 持久态转换为瞬时态:执行Session#delete()方法,需要注意的是被删除的持久话对象,不建议再次使用。
  • 持久态转化为脱管态:执行Session#evict()Session#close()Session#clear()方法。Session#evict()方法用于清楚一级缓存中某一个对象;Session#close()方法用于关闭 Session,清楚一级缓存;Session#clear()方法用于清楚一级缓存的所有对象。

脱管态对象转换到其他状态
脱管态对象无法直接获得,是由其他状态对象转换而来的,脱管态对象转换到其他状态总结如下:

  • 脱管态转换为持久态:执行Session#update()Session#saveOrUpdate()Session#lock()方法。
  • 脱管态转换为瞬时态:将脱管态对象的持久话标志 OID 设置为 null;

脱管态转换到瞬时态跟瞬时态转换到脱管态的情况相似,脱管态和瞬时态的区别就是 OID 有没有值,所以可以通过脱管态对象的 OID 设置为 null,使其编程瞬时态对象。例如在Session#close()操作后,加入代码customer.setCust_id(null);,customer 对象将由脱管态转换为瞬时态。