`

Hibernate对象的生命周期

    博客分类:
  • S2SH
阅读更多
一、情景描述

鉴于:hibernate是面向对象(实体、entity)操作,而不是某个对象的字段或属性。
鉴于:使用hibernate从数据库获取对象后,无需对数据库操作,而是直接操作获取的对象,hibernate就可以自动同步数据库。

因此:hibernate将对象分为三种状态,以便进行区分和管理:

1:瞬时/临时(Transient)
     可以理解为该对象和hibernate一点关系也没有。
     对该对象的操作不会和hibernate有任何联系或影响。

2:持久(Persistent)
    使用hibernate对该对象进行管理,这会涉及到hibernate自动对数据库的相应的操作。

     更细节的解释:
    (hibernate通过对外提供session对象,和session对象的一系列方法,完成对数据的增删改查。hibernate自动对数据库的操作也是依赖于和session绑定)。
    也就是说,在持久状态下,hibernate对对象的操作和seesion是分不开的。

3:脱管/游离(Detached)
     这种状态是根据hibernate是否建立了session链接,以便与第2种状态进行区分。
     可以理解为除了没有建立session(未连接数据库),其它的和第2种状态都一样。
     hibernate已经对该对象进行绑定,并管理。只是没有建立session链接。




二、词汇定义




1:瞬时/临时(Transient) - 由new操作符创建,且尚未与Hibernate Session 关联的对象被认定为瞬时的。瞬时对象不会被持久化到数据库中,也不会被赋予持久化标识(identifier)。 如果瞬时对象在程序中没有被引用,它会被垃圾回收器销毁。

2:持久(Persistent) - 持久的实例在数据库中有对应的记录,并拥有一个持久化标识。 持久的实例可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的Session作用范围内。 Hibernate会检测到处于持久状态的对象的任何改动,在当前操作单元执行完毕时将对象数据与数据库同步。开发者不需要手动执行UPDATE。

3:脱管/游离(Detached) - 与持久对象关联的Session被关闭后,对象就变为脱管的。 对脱管对象的引用依然有效,对象可继续被修改。脱管对象如果重新关联到某个新的Session上, 会再次转变为持久的,在脱管期间的改动将被持久化到数据库。




三、理解这三种状态的意义


便于使用hibernate提供的各种方法。意义是重大的。
比如:
merge()
session.close()对对象状态的影响
获取新的session后,对象状态,对数据库造成的影响。





四、讨论

说,这三种状态是hibernate的对象的生命周期,是不准确的。
因为每个状态都不是对象必须经过的。
但是这对象在这三种状态中可以相互转换。
就是状态。对象在hibernate中所表示的三种状态。


五、应用举例


1、关于merge方法

什么时候用?:
这个方法就是为在前台修改从后台读取的数据准备的。

【hibernate 需要设置为: hibernate update部分更新。因为直接使用merge()方法,会把数据库中有而传递过来的对象中没有的字段,会重置。这样就得在传参数时,把数据库中的字段都得写全。
具体参照:】
http://www.cnblogs.com/hyteddy/archive/2011/07/21/2113175.html

【其实,merge()方法解决了新new一个对象时,如何将其同步到数据库中去的问题。但是,需要把所有的字段写全,需要在前台页面中添加隐藏变量,这显然是不一个好方法。关于如何实现hibernate部分字段更新问题,请看这里(内容会拷贝到本文后面):】
http://www.rritw.com/a/JAVAbiancheng/Hibernate/20101207/52757.html

session.merge ()方法对状态的变化
    public void run() {    
          UserInfo userInfo = new UserInfo();//创建UserInfo实例          
          userInfo.setId(11112);//使之成为脱管状态
          userInfo.setName("RW3");
          userInfo.setSex("M");
          
          UserInfo userInfo2 = new UserInfo();//创建UserInfo实例         
          userInfo2.setId(11112); //使之成为脱管状态
          userInfo2.setName("RW4");
          userInfo2.setSex("F");          
          
          Session session = HibernateSessionFactory.currentSession();//启动Session          
          Transaction tx = session.beginTransaction();//启动事务          
          
          //调用merge方法,此时UserInfo实体状态并没有被持久化
          //但是数据库中的记录被更新了
          ①session.merge(userInfo);          
          session.merge(userInfo2);//调用merge方法,此时UserInfo实体状态并没有被持久化
          
          //merge方法与update方法的差别在于针对同样的操作update方法会报错
          //原因在于update方法使得实体状态成为了持久化状态,而Session中不允许两个持久化实体有同样的持久化标识
          ②//session.update(userInfo);
          //session.update(userInfo2);
          //以下两句不会发送SQL,因为userInfo2不是持久化状态的实体
          ③userInfo2.setName("RW5");
          userInfo2.setSex("M");

          //提交事务
          tx.commit();
          //关闭Hibernate Session
          HibernateSessionFactory.closeSession();
    }

关于使用setId()后对象就成为托管状态,可以这么猜测:hibernate对我们new的实体类进行了管理。

针对该段代码将执行如下SQL语句:
Hibernate:
/* ①session.merge(userInfo2)的动作 */
select
        userinfo0_.id as id0_0_,
        userinfo0_.NAME as NAME0_0_,
        userinfo0_.SEX as SEX0_0_,
        userinfo0_.roomid as roomid0_0_
    from
        userinfo userinfo0_
    where
        userinfo0_.id=?

Hibernate:
/* ①session.merge(userInfo2)的动作 */
update
            userinfo
        set
            NAME=?,
            SEX=?,
            roomid=?
        where
            id=?

session.merge()方法会首先发送一句select语句,去数据库端获取UserInfo持久化标识所对应的表记录;
然后自动生成一个持久化状态的UserInfo实体,与脱管状态的UserInfo实体做比较是否有所改变;一旦发生了改变,才会发送update语句执行更新。

而按执行顺序,若两句session.merge()方法针对同一个脱管状态的UserInfo实体,
那其结果只会执行最后一个session.merge()方法所发出的update语句。
即使执行了session.merge()方法,UserInfo实体依然是脱管状态,
因此③userInfo2. setName("RW5")的语句不会同步数据库中的表。




扩展阅读:
http://selvemen.iteye.com/blog/457225


2、我看merge()

merge的作用:对于一个对象(无论是否是新new的,还是处于游离态的):
    如果数据库中有对应的ID,则会update;
    如果没有,则会insert;

使用merge方法后,对对象之前的状态,不产生任何影响。
    即:对象在使用merge()方法之前是什么状态,使用merge()方法后还是什么状态。


   
例子:
    下面是当对象(str1)在第一个session关闭后,处于游离状态。
    第二个session开启,又get或load一样的ID的数据出来时, 对那个游离态对象(str1),使用update肯定会出错,原因是持久层中已经有对象(str2),你的update会让那个游离态对象也变成持久态,两个持久态会冲突。
    然而用merge的话,它会把第一个的对象数据赋值给已经处于持久化的那个对象中,而自己本身不得变为持久态;
    Session session1 = HibernateUtils.getSession();
    Transaction transaction1 = session1.beginTransaction();
    Students str1 = (Students)session1.get(Students.class, 2);
    transaction1.commit();
    session1.clear();
    session1.close();//session关闭,str1为游离态(detached)

    Session session2 = HibernateUtils.getSession();
    Transaction transaction2 = session2.beginTransaction();
    Students str2 = (Students)session2.get(Students.class, 2);
    str1.setName("wer");
    session2.merge(str1);//更新数据库
    System.out.println(str2.getName());  //这里改变了。因为str2是持久状态的。
    str2.setName("ee");
    System.out.println(str1.getName());   //这里不会改变,说明对str1使用merge()后没有被持久化;
    transaction2.commit();
    session2.clear();
    session2.close();







===============================================
题外话题
hibernate部分字段更新的解决方案

在调用Hibernate的update方法时会更新对象的全部字段,若对象属性值为null,则相应的数据库字段也会被更新为空值。
通常的做法 是先将需要更新的对象加载上来,再将需要更新的属性值一个个的setter到对象中,但这样显然影响了代码的可读性,而且在使用 Struts2+hibernate进行开发时,页面传递参数后Struts2会将对象进行自动赋值,已经赋值的对象在更新前又要进行一次手动赋值再 update,这样明显散失去了sturts2的自动赋值的意义。

解决方法:

将需要更新的对象加载上来后,利用BeanUtils类的copyProperties方法,将需要更新的值copy到对象中,最后再调用update方法。

注 意:这里推荐使用的方法并非org.apache.comm*****.beanutils包中的方法,而是 org.springframework.beans.BeanUtils中的copyProperties方法。原因是Spring工具类提供了 copyProperties(source, target, ignoreProperties)方法,它能在复制对象值的时候忽略指定属性值,保护某些值不被恶意修改,从而更安全的进行对象的更新。此外,根据一些 测试结果spring中的copyProperties方法效率要高于apache的方法(这点未作进一步验证)。

参考代码:

Admin persistent = adminService.load(id);// 加载对象
BeanUtils.copyProperties(admin, persistent, new String[]{"id", "username"});// 复制对象属性值时忽略id、username属性,可避免username被恶意修改
adminService.update(persistent);// 更新对象

具体代码可参考SHOP++源代码。
以上为SHOP++技术教程。来源:http://www.shopxx.net

本文摘自:http://chinaxxren.javaeye.com/blog/834675













--
引用:
http://zhidao.baidu.com/question/469345066.html
http://blog.csdn.net/lang_man_xing/article/details/7572964















-
  • 大小: 9.4 KB
分享到:
评论

相关推荐

    hibernate的生命周期

    **hibernate的生命周期** ...总之,理解并熟练掌握Hibernate对象的生命周期,对于编写高效、可靠的Java应用程序至关重要。正确管理对象状态,合理使用生命周期方法,能帮助我们避免不必要的数据库操作,提升应用性能。

    hibernate session生命周期示例

    本示例将深入探讨Hibernate Session的生命周期及其使用,帮助你更好地理解和运用这个强大的工具。 Hibernate Session是Hibernate的核心接口,它是与数据库交互的主要接口。Session对象负责管理实体对象的状态,包括...

    Hibernate持久化对象的生命周期

    Hibernate的核心概念之一就是持久化对象的生命周期,这涉及到对象在数据库中的状态及其与Session的关系。 首先,我们来看一下Hibernate中持久化对象的三种基本状态: 1. **瞬时对象(Transient Objects)**: - ...

    hibernate3.2生命周期

    总结,理解Hibernate3.2中的对象生命周期是有效使用Hibernate的关键。正确管理对象状态,能够避免数据丢失,提高应用程序性能,并减少潜在的并发问题。深入源码和使用专业工具能进一步提升开发效率。

    hibernate持久化对象生命周期[参照].pdf

    本文将深入探讨Hibernate中的持久化对象生命周期,包括瞬时对象、持久化对象和游离对象的状态转换及其特性。 1. 瞬时对象(Transient Objects) 瞬时对象是指通过`new`操作符创建但尚未与数据库记录关联的Java对象...

    测试实体对象的生命周期

    在IT行业中,尤其是在Java开发领域,实体对象的生命周期管理是至关重要的一个环节,尤其是在使用ORM(Object-Relational Mapping)框架如Hibernate时。本文将详细探讨“测试实体对象的生命周期”,并结合给定的标签...

    Hibernate 对象的三种状态和特点

    这些状态决定了对象与数据库之间的关联程度,以及Hibernate如何处理对象的生命周期。以下是Hibernate对象的三种主要状态及其特点: 1) 临时状态(Transient State): 当通过`new`关键字创建一个新的对象时,该对象...

    08 领域对象的生命周期 102-116.rar

    9. **生命周期方法**:在某些编程语言和框架中,领域对象可能包含一些生命周期方法,如 `save()`、`delete()`、`load()` 等,用于操作对象的生命周期。 10. **CQRS(命令查询责任分离)**:在复杂系统中,CQRS 模式...

    Hibernate考试题.pdf

    8. Hibernate对象生命周期: - Hibernate管理的对象生命周期包括瞬时态(Transient)、持久态(Persistent)、托管态(Managed)、脱管态(Detached)和删除态(Removed)。 以上就是“Hibernate考试题.pdf”中...

    利用 hibernate对象持久化服务简化数据库访问

    SessionFactory 是线程安全的,可以在应用的整个生命周期中被多个线程共享。Session 对象是非线程安全的,每个线程都应该拥有自己的 Session 实例。 当应用程序通过 Session 执行 CRUD 操作时,Hibernate 会自动将 ...

    hibernate中的对象关系模型

    在Hibernate中,通过`@ManyToOne`或`@OneToOne`注解表示,但需要注意的是,聚合关系通常不会影响对象的生命周期。 这些关系模型在Hibernate中通过注解或者XML配置文件进行定义,以实现Java对象和数据库记录之间的...

    Hibernate 操纵持久化对象

    Hibernate允许开发者定义对象的生命周期回调方法,如preInsert()、postInsert()、preUpdate()等,以便在对象状态改变时执行特定的业务逻辑。 **九、懒加载与立即加载** 懒加载(Lazy Loading)是一种优化策略,只在...

    Hibernate 对象持久化

    在Hibernate中,对象的生命周期包括瞬时态、托管态、持久态和脱管态。通过Hibernate,我们可以轻松地将对象从内存中保存到数据库,或者从数据库中加载到内存。 **三、Hibernate配置** 使用Hibernate,首先需要配置...

    Hibernate 面试题

    1. **持久化对象的生命周期**:在Hibernate中,对象经历了临时态、持久态和游离态三个状态。临时态的对象没有与Session关联,数据未保存到数据库;持久态对象已与Session绑定,其状态会随Session的提交而保存到...

    hibernate对象三状态及OneToOne&OneToMany&ManyToMany

    一旦对象变为持久态,Hibernate会负责它的生命周期管理,包括插入、更新和删除操作。 二、一对一(OneToOne)关系映射 在数据库设计中,一对一关系意味着两个实体表之间存在唯一映射。在Hibernate中,可以通过@...

    精通Hibernate:Java对象持久化技术详解

    6. **实体生命周期管理**:Hibernate自动管理对象的状态,包括瞬态、持久化、托管和脱管四种状态,以及它们之间的转换。 7. **多对一、一对多、多对多关系映射**:Hibernate支持复杂的关联关系映射,如单向关联、...

    Hibernate对象持久化状态

    在 Hibernate 框架中,Java 对象...开发者应合理管理 Session 生命周期,避免并发问题,确保数据的一致性和完整性。同时,根据具体应用需求,选择合适的缓存清理策略和对象状态转换时机,以达到最佳的数据库操作效果。

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     23.1.1 Session对象的生命周期与本地线程绑定  23.1.2 Session对象的生命周期与JTA事务绑定  23.2 实现对话  23.2.1 使用游离对象  23.2.2 使用手工清理缓存模式下的Session  23.3 小结  23.4 思考题 第24章...

Global site tag (gtag.js) - Google Analytics