持久化对象的状态

  站在持久化的角度,Hibernate把对象分为了4种状态:持久化状态,临时状态,游离状态和删除状态。Session的特定方法能使对象从一个状态转换到另一个状态。
  

  • 临时对象(Transient):
    在使用代理主键的情况下,OID 通常为 null;
    不处于Session的缓存中;
    在数据库中没有对应的记录。
    通常使用new创建一个新的对象,并且不设置它的id属性值,则这个对象就是临时对象。
  • 持久化对象 (也叫“托管”)(Persist):
    OID不为null;
    位于Session缓存中;
    若在数据库中已经有和其对应的记录,则持久化对象和数据库中的相关记录对应;
    Session在flush缓存时,会根据持久化对象的属性变化,来同步更新数据库;
    在同一个Session实例的缓存中,数据库表中的每条记录只对应唯一的持久化对象。
  • 游离对象 (也叫”脱管”) (Detached):
    OID不为null;
    不再处于Session缓存中;
    一般情况需下,游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录。
  • 删除对象 (Removed):
    在数据库中没有和其OID对应的记录;
    不再处于Session 缓存中;
    一般情况下,应用程序不该再使用被删除的对象。

      这几种状态的对象转换图如下:
      
    image_1b327ru1f18eg1169tqfi771p429.png-81.6kB
     
    下面介绍Session能够转换对象状态的方法:

  • save()
    Session 的 save() 方法使一个临时对象转变为持久化对象;
    Session 的 save() 方法完成以下操作:
    1. 把 News 对象加入到 Session 缓存中,使它进入持久化状态;
    2. 选用映射文件指定的标识符生成器, 为持久化对象分配唯一的 OID。
    (在使用代理主键的情况下, setId() 方法为 News 对象设置 OID 是无效的)
    3. 计划执行一条 insert 语句:在 flush 缓存的时候,hibernate 通过持久化对象的 OID 来维持它和数据库相关记录的对应关系,当 News 对象处于持久化状态时, 不允许程序随意修改它的 ID
     
    persist() 和 save() 区别:
    当对一个OID不为Null的对象执行save()方法时,会把该对象以一个新的OID保存到数据库中; 但执行persist()方法时会抛出一个异常。

  • get() 和 load()
    1. 这两个方法都可以根据给定的 OID 从数据库中加载一个持久化对象;
    2. 执行 get 方法: 会立即加载对象;(立即检索)
    执行 load 方法:若不使用该对象,则不会立即执行查询操作,而返回一个代理对象,直到使用到该对象的时候才会加载。(延迟检索)
    3. 如果在需要初始化代理对象之前已经关闭了session,load方法可能会抛出 LazyInitializationException 异常(懒加载异常)。例如:下面这段代码会抛出懒加载异常:

public void testLoad(){

        News news = (News) session.load(News.class, 1);

        session.close();
        System.out.println(news); 
    }

image_1b329j3m7evin1so5j1nln7dam.png-24.2kB
而下面这段代码则可以正常加载:

public void testLoad(){

        News news = (News) session.load(News.class, 1);

        System.out.println(news);
        session.close();
        System.out.println(news); 
    }

image_1b329lqrt12o41tdi1ap71fm71m8613.png-10kB

4. 若数据表中不存在与OID对应的记录,且Session也没有被关闭:
 get方法会返回null;
 load方法若不使用该对象的任何属性,则不会出现问题;否则将抛出ObjectNotFoundException异常。

  • update()
    1. Session 的update()方法可以使一个游离对象转变为持久化对象,并且计划执行一条 update 语句。
    2. 若希望Session仅在对象的属性发生变化时, 才执行 update() 语句,可以把映射文件中 <class> 元素的 select-before-update 设为 true,该属性的默认值为 false。(若该对象是持久化对象,且其属性并未发生改变,则就算不配置select-before-update为true,也不会进行update操作)
    3. 若更新一个持久化对象,通常不需要显示的调用update方法,因为在调用Transaction的commit()方法时,会先执行session的flush方法。
    4. 当update()方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同OID的持久化对象,会抛出异常,因为在Session 缓存中不能有两个OID相同的对象。
    5. 当update()方法关联一个游离对象时,如果在数据库中不存在相应的记录, 也会抛出异常。

  • saveOrUpdate()
    首先判断保存的对象是临时对象还是游离对象,若为临时对象,则调用save()方法,若是游离对象,则调用update()方法。
    判定对象为临时对象的标准:
    标准一: Java 对象的 OID 是否为 null,为null是临时对象,否则是游离对象。
    标准二: 如果在映射文件中为 <id> 设置了unsaved-value属性, 则OID取值等于这个unsaved-value属性值的Java对象为临时对象,否则为游离对象。
     
      saveOrUpdate执行流程如下:
     
    image_1b32btj7e16cs1un51n8li3p1f9v1g.png-19.5kB

  • delete()
    1. Session 的delete()方法既可以删除一个游离对象,也可以删除一个持久化对象。只要 OID 和数据表中一条记录对应,就会准备执行 delete 操作,若 OID 在数据表中没有对应的记录,则抛出异常。
    2. Session 的 delete() 方法处理过程为:计划执行一条delete 语句,把对象从 Session 缓存中删除,然后该对象进入删除状态。
    3. 默认情况下,在执行delete方法后,对象的id值仍然被保存在对象中,这在某些情形下(例如又对该对象执行saveOrUpdate()方法)会很不方便。Hibernate的配置文件hibernate.cfg.xml中有一个hibernate.use_identifier_rollback属性,其默认值为false,若把它设为true,则在执行delete()方法后,对象的id值将被置为null。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值