Hibernate入门16 - 对象状态与识别

入门 16 - 对象状态与识别

 在之前的主题大致了解Hibernate的基本操作与ORM之后,我们来重新探讨一些Hibernate底层的一些机制,首先从Hibernate的对象状态开始讨论。
 Hibernate中的对象可以分为三种状态:暂存(Transient)对象、持久(Persistent)对象、分离(Detached)对象。
 暂存对象指的是在Java程序流程中,直接使用new制作出之对象,例如在之前的例子中,User类别所衍生出之对象,在还没有使用save()之前都是暂存对象,这些对象还没有与持久层发生任何的关系,只要没有名称参考至该对象,该对象就会在适当的时候被回收。
 如果暂存对象使用save()或saveOrUpdate()方法将其状态存储至持久层,则此时暂存对象转变为持久对象,持久对象会拥有与数据库中相同 的识别(identity),在我们对对象的设计中,也就是对象的id属性所持有(被赋予)的值,会与数据库识别(database identity)相同。如果是直接进行数据库查询所返回的数据对象,例如使用find()、get()、load()等方法查询到的数据对象,这些对象 都与数据库中的字段相关,具有与数据库识别值相同的id值,它们也马上变为持久对象。另外如果一个暂存对象被持久对象参考到,该对象也会自动变为持久物件,这是持久层管理员(Persistance Manager)自行透过演算查询到关联并作的操作,这之后的主题还会探讨。
 持久对象如果在其上使用delete(),就会变回暂存对象,这是当然的,如果使用delete()后,数据库中将没有与该对象对应的字段,对象与数据库不再有任何的关联。
 持久对象总是与session及transaction相关联,在一个session中,对持久对象的改变不会马上对数据库进行变更,而必须在 transaction终止,也就是执行commit()之后,在数据库中真正运行SQL进行变更,持久对象的状态才会与数据库进行同步,在同步之前的持 久对象,我们称其为dirty。
 当一个session执行close()或是clear()、evict()之后,持久对象会变为分离对象,这个时候的对象的id虽然拥有数据库识别 值,但它们目前并不在Hibernate持久层管理员的管理之下,它与暂存对象本质上是相同的,在没有任何名称参考至它们时,会在适当的时候被回收。
 分离对象拥有数据库识别值,所以它可以透过update()、saveOrUpdate()、lock()等方法,再度与持久层关联,通常的应用是,您 从数据库查询一笔数据,关闭session以将联机资源让出,此时对象是分离状态,使用者经过一小段时候操作分离对象(像是购物车),然后重新开启一个 session,将分离对象与session相关联,然后将变更结果存回数据库。
 大致了解对象状态之后,我们还有讨论一下对象识别问题,对数据库而言,其识别一笔数据唯一性的方式是根据主键值,如果手上有两份数据,它们拥有同样的主 键值,则它们在数据库中代表同一个字段的数据。对Java而言,要识别两个对象是否为同一个对象有两种方式,一种是根据对象是否拥有同样的内存位置来决定,在Java语法中就是透过==运算来比较,一种是根据equals()、hasCode()中的定义。
 先探讨第一种Java的识别方式在Hibernate中该注意的地方,在Hibernate中,如果是在同一个session中根据相同查询所得到的相同数据,则它们会拥有相同的Java识别,举个实际的例子来说明:

Session session = sessions.openSession();

Transaction tx = session.beginTransaction();

Object obj1 = session.load(User.class, new Long(007));

Object obj2 = session.load(User.class, new Long(007));

tx.commit();

session.close();

 

System.out.println(obj1 == obj2);


 上面这个程序片段将会显示true的结果,表示obj1与obj2是参考至同一对象,但如果是以下的情况则不会显示false:

Session session1 = sessions.openSession();

Transaction tx1 = session1.beginTransaction();

Object obj1 = session1.load(User.class, new Long(007));

tx1.commit();

session1.close();

 

Session session2 = sessions.openSession();

Transaction tx2 = session1.beginTransaction();

Object obj1 = session2.load(User.class, new Long(007));

tx2.commit();

session2.close();

 

System.out.println(obj1 == obj2);


 简单的说,在两个不同的session中,Hibernate不保证两个对象拥有相同的参考。
 如果您想要比较两个不同的session所得到的数据是否相同,您可以定义equals()与hasCode(),根据您的实际需求定义好,并使用obj1.equals(obj2)的方式来比较对象所真正拥有的值,下一个主题中我们再来讨论相关的细节。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值