Hibernate 的三种状态 持久化 游离 临时 的关系

临时(Transient) - 由new操做符建立,且还没有与Hibernate Session 关联的对象被认定为临时(Transient)的。临时(Transient)对象不会被持久化到数据库中,也不会被赋予持久化标识(identifier)。 若是临时(Transient)对象在程序中没有被引用,它会被垃圾回收器(garbage collector)销毁。 使用Hibernate Session能够将其变为持久(Persistent)状态。(Hibernate会自动执行必要的SQL语句)

持久(Persistent) - 持久(Persistent)的实例在数据库中有对应的记录,并拥有一个持久化标识(identifier)。 持久(Persistent)的实例多是刚被保存的,或刚被加载的,不管哪种,按定义,它存在于相关联的Session做用范围内。 Hibernate会检测处处于持久(Persistent)状态的对象的任何改动,在当前操做单元(unit of work)执行完毕时将对象数据(state)与数据库同步(synchronize)。 开发者不须要手动执行UPDATE。将对象从持久(Persistent)状态变成瞬时(Transient)状态一样也不须要手动执行DELETE语句。

游离(Detached) - 与持久(Persistent)对象关联的Session被关闭后,对象就变为游离(Detached)的。 对游离(Detached)对象的引用依然有效,对象可继续被修改。游离(Detached)对象若是从新关联到某个新的Session上, 会再次转变为持久(Persistent)的(在Detached其间的改动将被持久化到数据库)。 这个功能使得一种编程模型,即中间会给用户思考时间(user think-time)的长时间运行的操做单元(unit of work)的编程模型成为可能。 咱们称之为应用程序事务,即从用户观点看是一个操做单元(unit of work)。
Hibernate中对象的游离状态是指Session关闭以后,持久化对象变成离线对象,离线对象就不能同数据库同步,也再也不受Hibernate管理。操做 处于游离态对象 常常会报 session已关闭的错误。

举例
有两个类, Team, Person. 映射关系是Team一对多Person, 采用lazy fetch策略。
session begin
Team t = *Dao.get()
session end
t.getPersons()// 出错
若是是用spring管理session的状况,事务外操做t.getPerons()也跟上面状况同样。
这种状况在生产环境多表现为在jsp页面操做 t对象时出错。
解决方法:
1. 取消lazy fetch策略
缺点:会致使过多的数据库访问,由于是一对多的状况。
2. 在事务内就先把关联的对象取出
缺点:会致使service层方法不统一,由于要分开取出与不取出的状况。
3. 使用spring的 openSessionInview机制
缺点: session打开的时间比较长, 使用很差可能会致使out of memory

一个游离态的对象转换为持久战态,有如下几种方法:
一、session.saveOrUpdate(object)。这语句会把游离态的PO转为持久态的PO并提交给数据库
二、session.merge(object)。这语句会把游离态的PO转为持久态的PO,并进行合并操做。
三、session.lock(object, LockMode.NONE)。这语句只会把游离态的PO转为持久态PO,不做其余操做。不过,PO必须是没有修改过的,这方法挺适合作一个应用层。spring

相关文章
相关标签/搜索