持久化层的Java对象可处在哪些状态?这些状态有哪些特征

持久化层的Java对象可处于哪些状态?这些状态有哪些特征?

当应用程序通过new语句创建了一个对象,这个对象的生命周期就开始了,当不再有任何引用变量引用它,这个对象就结束生命周期,它占用的内存就可以被JVM的垃圾回收器回收。对于需要被持久化的Java对象,在它的生命周期中,可处于以下三个状态之一:

(1) 临时状态(transient):刚刚用new语句创建,还没有被持久化,不处于Session的缓存中。处于临时状态的Java对象被称为临时对象。

(2)持久化状态(persistent):已经被持久化,加入到Session的缓存中。处于持久化状态的Java对象被称为持久化对象。

(3) 游离状态(detached):已经被持久化,但不再处于Session的缓存中。处于游离状态的Java对象被称为游离对象。

持久化层的Java对象可处在哪些状态?这些状态有哪些特征

图1为Java对象的完整状态转换图,Session的特定方法触发Java对象由一个状态转换到另一个状态。从图1看出,当Java对象处于临时状态或游离状态,只要不被任何变量引用,就会结束生命周期,它占用的内存就可以被JVM的垃圾回收器回收;当处于持久化状态,由于Session的缓存会引用它,因此它始终处于生命周期中。

 

临时对象的特征

临时对象具有以下特征:
(1) 不处于Session的缓存中,也可以说,不被任何一个Session实例关联。
(2) 在数据库中没有对应的记录。

在以下情况下,Java对象进入临时状态:
(1) 当通过new语句刚创建了一个Java对象,它处于临时状态,此时不和数据库中的任何记录对应。
(2) Session的delete()方法能使一个持久化对象或游离对象转变为临时对象。对于游离对象,delete()方法从数据库中删除与它对应的记录;对于持久化对象,delete()方法从数据库中删除与它对应的记录,并且把它从Session的缓存中删除。

持久化对象的特征

持久化对象具有以下特征:
(1) 位于一个Session实例的缓存中,也可以说,持久化对象总是被一个Session实例关联。
(2) 持久化对象和数据库中的相关记录对应。
(3) Session在清理缓存时,会根据持久化对象的属性变化,来同步更新数据库。

Session的许多方法都能够触发Java对象进入持久化状态:
(1) Session的save()方法把临时对象转变为持久化对象。
(2) Session的load()或get()方法返回的对象总是处于持久化状态。
(3) Session的find()方法返回的List集合中存放的都是持久化对象。
(4) Session的update()、saveOrUpdate()和lock()方法使游离对象转变为持久化对象。(nate注:根据hibernate reference的说法当试图用update更新一个持久化对象时会抛异常)
(5)当一个持久化对象关联一个临时对象,在允许级联保存的情况下,Session在清理缓存时会把这个临时对象也转变为持久化对象。

游离对象的特征

游离对象具有以下特征:
(1) 不再位于Session的缓存中,也可以说,游离对象不被Session关联。
(2) 游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录(前提条件是没有其他程序删除了这条记录)。

游离对象与临时对象的相同之处在于,两者都不被Session关联,因此Hibernate不会保证它们的属性变化与数据库保持同步。游离对象与临时对象的区别在于:前者是由持久化对象转变过来的,因此可能在数据库中还存在对应的记录,而后者在数据库中没有对应的记录。

Session的以下方法使持久化对象转变为游离对象:
(1) 当调用Session的close()方法时,Session的缓存被清空,缓存中的所有持久化对象都变为游离对象。如果在应用程序中没有引用变量引用这些游离对象,它们就会结束生命周期。
(2)Session的evict()方法能够从缓存中删除一个持久化对象,使它变为游离状态。当Session的缓存中保存了大量的持久化对象,会消耗许多内存空间,为了提高性能,可以考虑调用evict()方法,从缓存中删除一些持久化对象。但是多数情况下不推荐使用evict()方法,而应该通过查询语言,或者显式的导航来控制对象图的深度

 

--------------------------------------------------------

public void Update()
{
Session session = factory.openSession();
User user = (User) session.get(User.class, new Integer(2));
//User user = (User) session.load(User.class, new Integer(2));
session.clear();
user.setAddress("SSSSSSSSS");
session.beginTransaction().commit();
session.close();
}
如果用get就象视频里一样成功把session对象变成游离状态更新无效
但是换成load就执行了update语句成功更改。。。
百度出来大部分说区别也只是如果数据库没有对象时候返回NULL和抛异常~
以下是文档的方法注释
load
Read the persistent state associated with the given identifier into the given transient instance.

get
Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance. (If the instance, or a proxy for the instance, is already associated with the session, return that instance or proxy.)
------------------------------------------------

什么是延迟加载,当操作对象时,如果没有用到对象的属性则不会进行数据库操作,当用到对象的相应属性时才进行数据库操作
比如:
Session session = sessionFactory.buildSession();
SomeClass someClass = (SomeClass)session.load(SomeClass.class,new Integer(2));
些时hibernate并没有执行,而是在session中加载了someclass对象,当我们用到someclass的属性时才加载该对象,
someClass.getProperties();//此时加载对象,执行sql语言
load():支持延迟加载。
get():不支持延迟加载

调用get()之后,user对象装载到内存中了,当再调用session.clear()方法会回收此对象。所以再更新,就会出现空指针异常,因为此对象已经回收,user==null
而用load()方法。支持延迟加载,再调用session.clear()回收已经加载的对象(此时延迟加载user对象并没有加载到内存),所以可以调用 user.setAddress("SSSSSSSSS");