不论是EJB3.0还是Hibernate,他们统称为ORM框架。虽然每个框架对对象的状态都有自己的理解,但是都免不了有共性的东西。
在Hibernate中,对象的状态分为Transient、Persist、Detached,而在EJB中有四种状态,分别为:New、Managed、Detached、Removed。
其中Transient和New对应,都是未有Id值(随后说下这个Id是什么意思),尚未放在数据库映像(SessionFactory、PersistenceContext)中,对此数据进行修改,数据库中的数据不会改变。
Persist与Managed对应,是被容器管理的对象,也称为持久化对象。对此对象进行操作会影响数据库中的数据。
二者的Detached个人感觉是一样的,是离线对象的意思。表明此对象未删除,只是实体管理对象关闭了而已,并不是删除。
二者关于对象状态的偏差就是EJB多了一个Removed状态,此状态是在你remove对象后,对象进入此状态。而在Hibernate中,如果调用了remove方法,对象会进入Transient状态,由于目前对removed状态接触的不多,所以暂时就将它归为Transient状态吧。其实EJB这样分也是有一定道理的。下面就进行详细说明
ORM对状态的分类,其实是根据Id和是否被管理来区分的:
大家都知道,在用这两个ORM的时候,除了要将类声明为Entity,另外不可少的一步就是必须声明Id生成策略。新new的对象,在Session或EntityManager(后面同意成为Session)调用save方法后,会给对象赋予Id,这样这个对象就同时被Session管理和有了Id。也就是Persist状态的对象,对此状态的对象进行修改,会默认调用session的update方法。
新new的对象在save之前,状态为Transient,此时对象未被分配Id,未被容器管理,所以你无论怎样修改,它都只是一个普普通通的Java对象。
出于Detached状态的对象,如果你此时将Session关闭,那么这个对象就有Id,而未被容器管理,所以此对象从某个角度来说,只是一个又Id的Transient对象而已,也就是说你自己New一个对象,然后将此对象的Id进行赋值,那么此对象就可以说是一个Detached对象,只不过里面的值和数据库中的值有些差别而已,如果你显式调用update方法,如果你的Id在数据库中有,那么它是可以更新上去的。
EJB的划分之所以为4种,是因为他自己给自己挖了一个坑,关于New的描述是这样的:未有Id值,尚未被容器管理。其实这样说很简单,让人也很容易接受。我其实就是这样理解的,因为很通俗易懂,并且可以明显猜测到他的执行过程干了些什么。但是在Remove的时候,此类不再被容器所管理,但是有Id值,而且数据库中也没有,这三点同时囊括了New和Detached的特点,按照他的分类就不能放到这两种的任何一种,所以就多出来一个Removed状态。
回头再看一下Hibernate对于Transient的描述:使用New操作符初始化的对象不是立刻就持久化的,他们没有跟数据库表相关联行为,只要应用不在引用这些对象,他们的状态将会丢失,并由垃圾回收机制回收。所以在调用Remove方法后改对象就成了一个瞬时对象。
相比较Hibernate描述的更加抽象,但是理解起来是有一定困难的,因为如果不是你自己查看对象状态,你根本不知道Transient和Persist到底有什么差别,而EJB描述的具体了,就会发现这抽象的几种不够用。希望通过下面的一个表格,来很好的说明一下ORM中对象状态这回事。
(其中括号中的为EJB中的对象状态)
他们之间的状态转换如下: