Hibernate -- 持久化对象的三种状态
持久化对象三种状态的概述
Hiberante 为了更好的来管理持久化类,特将持久化类分成了三种状态。在 Hibernate 中持久化的对象可以划分为三种状态,分别是瞬时态、持久态和脱管态,一个持久化了的实例可能处于三种不同状态中的某一种,三种状态的详细介绍如下。
- transient 瞬时态
瞬时态也称为临时态或自由态,瞬时态的实例是由 new 命令创建、开辟内存空间的对象,不存在持久化标识 OID(相当于主键值),尚未与 Hibernate Session 关联,在数据库中也没有记录,失去引用后将被 JVM 回收。瞬时状态的对象在内存中是孤立存在的,与数据库中的数据无任何关联,仅是一个信息携带的载体。 - persistent 持久态
持久态的对象存在持久化标识 OID,加入到了 Session 缓存中,并且相关联的 Session 没有关闭,在数据库中由对应的记录,每条记录只对应唯一的持久化对象,需要注意的是,持久态对象是在事务还未提交前变持久态的。 - detached 脱管态
脱管态也称为离线态或游离态,当某个持久化状态的实例与 Session 的关联被关闭时就变成了脱管态。脱管态对象存在持久化标识 OID,并且仍然与数据库中的数据存在关联,只是失去了与当前 Session 的关联,脱管状态对象发生改变时 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 对象将由脱管态转换为瞬时态。