`

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持久化对象的生命周期 持久化对象的状态: 瞬时对象(Transient Objects)持久化对象(Persist Objects)、离线对象(Detached Objects)、 Java对象在JVM中的生命周期 理解Session的缓存 在Hibernate应用...

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

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

    精通 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章...

    对象-关系映射—Hibernate 培训 (中文)

    对象-关系映射—Hibernate 培训 (中文) 目录 一、持久化层-O/R Mapping 二、Hibernate入门 三、Hibernate映射申明(Mapping declaration...四、持久化对象的状态和生命周期 五、Hibernate查询 六、Hibernate最佳实践

    精通hibernate:对象持久化技术孙卫琴第二版part2

    本章站在持久化层的角度,Java对象在生命周期中可处于临时状态、持久化状态、删除状态和游离状态。处于持久化状态的Java对象位于一个Session实例的缓存中,Session能根据这个对象的属性变化来同步更新数据库。 8.1 ...

    Hibernate 面试题

    好用的Hibernate面试题资料,帮助你应聘J2EE的相关岗位

    一套不错的hibernate学习教程

    一套不错的hibernate教程,发现这里没有. 我是从百度上文库里搞来的,花了我30多分. 现在整合一起.只要5分啦.. 内容简介 --------------------------------- ...Hibernate对象的生命周期 ..............

    精通Hibernate:对象持久化技术第二版part3

    本章站在持久化层的角度,Java对象在生命周期中可处于临时状态、持久化状态、删除状态和游离状态。处于持久化状态的Java对象位于一个Session实例的缓存中,Session能根据这个对象的属性变化来同步更新数据库。 8.1 ...

    Hibernate 课件及源代码

    内容涵盖安装 Hibernatetools 插件、Session 核心方法、持久化对象生命周期、对象关系映射(1-n、1-1、n-n、继承映射)、检索策略、检索方式(对象导航图、OID 检索、HQL、QBC、本地SQL)、Hibernate 一\二级缓存、...

    Hibernate的Session的javadoc

    而且关于实体对象的生命周期也有很多概念不清,分不清transient、persistent、detached的区别,只是知道PO、VO这样的通俗叫法。其实这些概念都很简单,Hibernate的javadoc写的都很清楚,只需看看就能明白。

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

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

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

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

    Hibernate培训

    一、持久化层-O/R Mapping 二、Hibernate入门 三、Hibernate映射申明(Mapping declaration) 四、持久化对象的状态和生命周期 五、Hibernate查询 六、Hibernate最佳实践

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

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

    Hibernate4学习基础教程(26集)

    内容涵盖安装 Hibernatetools 插件、Session 核心方法、持久化对象生命周期、对象关系映射、检索策略、检索方式、Hibernate 一\二级缓存、管理 Session、批量处理等 Hibernate 企业级开发的核心技术。

    Hibernate学习笔记

    004 持久对象的生命周期介绍 005 query 接口初步 006 开源 O/R 映射框架内容回顾 007 Hibernate 基本映射标签和属性介绍 008 多对一 关联映射 009 一对一 主键关联映射_单向 010 一对一 主键关联映射_双向 011 一对...

    Hibernate+中文文档

    21.3. 级联生命周期(Cascading lifecycle) 21.4. 级联与未保存值(Cascades and unsaved-value) 21.5. 结论 22. 示例:Weblog 应用程序 22.1. 持久化类 22.2. Hibernate 映射 22.3. Hibernate 代码 23. ...

    Hibernate3 学习笔记.ppt

    Hibernate3 学习笔记.ppt 一、O/R Mapping 二、Hibernate入门 三、Hibernate映射申明(Mapping declaration) ...五、持久化对象的状态和生命周期 六、Hibernate查询 七、Hibernate最佳实践 八、Hibernate Tool

Global site tag (gtag.js) - Google Analytics