hibernate持久化实现——实体对象生命周期

来源:互联网 发布:海贼-王路飞 知乎 编辑:程序博客网 时间:2024/06/09 21:52

一、实体对象的三种状态:

这里说的实体对象,特指在hibernate O/R映射关系中的域对象。O/R指的是Object/Relation.

3种状态包括:

①:Transient(自由状态)

所谓transient,就是实体对象在内存中的自由存在,它与数据库中的记录无关。

Tuser user=new Tuser();
user.setName("came1");

这里的user对象,与数据库中的记录没有任何关联。

②:Persistent(持久状态)

所谓persistent,就是实体对象处于有hibernate框架所管理的状态。这种状态下,实体对象的引用被纳入hibernate实体容器中加以处理,其变更也将由hibernate固化到数据库中。

Tuser user=new Tuser();
user.setName("came1");//此时user出于transient状态

tran=session.beginTransaction();
session.save(user);//此时的user对象已经有hibernate纳入管理容器,
于persistent状态
tran.commit();


tran2=session2.beginTransaction();
user.setName("came22");
//由于此时user再次出于persistent状态,因此属性变更将自动有hibernate固化到数据库中。
tran2.commit();

可以看到,处于transient状态的实体对象,可以通过session.save方法转换到persistent状态。而同样,如果一个实体对象是有hibernate加载(如通过session.load方法获得),他也处于persistent状态。

Tuser user=(Tuser)session.load(Tuser.class,new Integer(1));

persistent状态的对象对应了数据库的提条记录,可以看做是数据库记录的对象化操作接口,其状态的变更将对数据库中的记录产生影响。

简而言之,如果一个实体对象与某个session实体发生了关联,并处于对应session的有效期内,那么它就处于persistent状态。

③:Detached(游离状态)

所谓detached状态,指的是处于persistent状态的对象在其对应的session关闭之后的状态。session实例可以看做是persistent对象的宿主,一旦此宿主失效,persistent对象即进入detached状态。

我们来看:

Tuser user=new Tuser();
user.setName("came1");//此时user出于transient状态

tran=session.beginTransaction();
session.save(user);//此时的user对象已经有hibernate纳入管理容器,出于persistent状态
tran.commit();

session.close();//user对象此时状态为detached,因为与其关联的session已经关闭。

在上面的例子中,user对象从persistent状态变为detached状态。那么这里的detached状态与transient状态有何区别?

区别就在于detached对象可以再次与某个session实例相关联而成为persistent对象。

Tuser user=new Tuser();
user.setName("came1");//此时user出于transient状态
tran=session.beginTransaction();
session.save(user);//此时的user对象已经有hibernate纳入管理容器,出于persistent状态
tran.commit();


tran2=session2.beginTransaction();
session2.update(user);
//此时出于detached状态的user对象借用session2再次被hibernate纳入管理容器,状态转换为persistent
user.setName("came22");
//由于此时user再次出于persistent状态,因此属性变更将自动有hibernate固化到数据库中。
tran2.commit();

在本人理解中,区别在于该对象再次与某个session实例相关联时,与该对象对应的数据库记录的不同。当处于transient状态时,在与某一个session关联以前,数据库中并没有对应该对象的记录。而detached对象在与另外的session重新关联时,对应的数据库记录已经存在。

在上述例子中,detached对象与最初的transient对象有何不同,既然detached对象已经与hibernate实体容器无关,那么这两者还有什么差异。

在session.save方法的执行过程中,user对象的内容已经发生了改变。

在创建 transient对象时,我们为user对象设定了一个name属性,此时user对象所包含的的数据信息也仅限于此。它与数据库的记录并不存在对应关系。

而在session.load执行之后,hibernate对user对象进行了持久化,并为其赋予了主键值。由于主键值可以唯一确定库表中的一条记录,那么这个user对象就可以与库表中具备相同id值得记录相关联。这就是前后两个状态的差异。transient状态的user对象与库表中的数据缺乏对应关系,而detached状态的user对象,却在库表中存在对应的记录。只不过由于detached对象脱离了session操作平台,它的变化无法更新到库表中的对应记录。

就目前的这个示例,transient状态中的实体对象无主键信息,而detached状态的实体对象,包含了其对应数据库记录的主键值。

我们可以人工制造一个detached对象:

Tuser user=new Tuser();
user.setName("came1");//此时user出于transient状态
//user.setId(3);//硬编码为其指定主键值,此时user对象成为人造的detached对象

此时我们手工构造的这个detached对象与通过session构造的detached对象并没有什么区别。

不过考虑到实际情况可能并非这么简单,hibernate对象在判定对象处于detached对象还是transient对象时,有着更加复杂的机制。在这里告诉大家hibernate怎么判断一个对象是否处于transient状态:

1.首先,对象的id属性(如果此属性存在的话),是否为空。

2.对于上面的示例,hibernate即根据此条件进行判定。

3.如果指定了id属性的unsaved-value,那么id属性是否等于unsaved-value

4.如果配置了Version属性,version属性是否为空。

5.如果配备了Version属性,且version指定了unsaved-value值,version属性是否等于unsaved-value。

6.如果存在Interceptor,那么Interceptor.isUnsaved方法是否返回true。

相对与persistent状态与detached状态的转变,实体对象从persistent状态转换成transient状态,一般有session.delete方法完成。

Tuser user=new Tuser();
user.setName("came1");//此时user出于transient状态

tran=session.beginTransaction();
session.save(user);//此时的user对象已经有hibernate纳入管理容器,出于persistent状态
tran.commit();

session.delete(user);
System.out.println(user.getId());

代码在最后打印出了id值,可以看到这个id值非null,这是否意味着user对象处于detached状态。在这里,这个id对应的库表记录已经被删除,此时的user对象与库表中的记录已经不存在对应关系,因此它处于transient状态。

VO和PO:

在三种状态中,transient对象和detached对象被称为VO,即值对象,persistent对象被称为持久化对象,即PO。这样的划分主要是基于“实体对象是否被纳入hibernate实体管理容器”的立场上的。

由于PO和VO的概念,又引申出一些系统层次设计方面的问题, 如在传统的MVC架构中,位于model层的PO,是否允许被传递到其他层面。由于PO的更新最终被影映射到数据库中,如果PO在其他层面(如view层)发生了变动,可能会对model层产生意想不到的破坏。

因此一般而言,应避免直接将PO传递到系统的其他层面,一种解决办法是通过构造一个新的VO,通过属性复制使其具备与PO相同的属性值,并以其为传输媒质。实际上,这个VO被用作Data Transfer Object,即DTO,将此VO传递给其他层面可以实现必须的数据传送。

属性复制可以通过Apache Jakarta Commons BeanUtils组件提供的属性批量复制功能,避免繁琐的get和set。

本篇文章来自“夏昕.深入浅出Hibernate”。

0 0
原创粉丝点击