hibernate优化策略01对象的三种状态


一、性能优化策略

  • 一级缓存和快照
  • 延迟加载策略
  • 抓取策略
  • 使用连接池
  • 二级缓存

要掌握这些性能优化策略,必须首先了解对象的三种状态

二、对象的三种状态

在 Hibernate 程序运行过程中,一个对象会存在以下的三种状态,分别为:
  • 瞬时态: 没有对象 OID 值,没有被 session 管理
  • 持久态:有对象 OID 值,已经被 session 管理
  • 脱管态:有对象 OID 值,已经脱离 session 管理

处于持久态的对象也称为 PO(Persistence Object),瞬时对象和脱管对象也称为 VO(Value Object)。
这3个状态是hibernate里pojo对象得3个状态, POJO(Plain Ordinary Java Object)简单的Java对象

测试三种状态:

public class StatusTest {
    /**
     * Hibernate对象的三种状态
     */
    @Test
    public void testStatus(){

        Session session = HibernateUtil.openSession();
        Transaction tx = session.beginTransaction();

        //1、此时:瞬时态
        Customer customer = new Customer();  //这时c对象没有OID值,没有被session管理,这时c对象就是瞬时态对象
        customer.setName("大老李");
        System.out.println(customer.getId());

        session.save(customer);
        //2、此时:持久态
        System.out.println(customer.getId());//这时c对象有OID值,被session管理,这时c对象就是持久态对象

        tx.commit();
        session.close();

        //3、此时:脱管态
        System.out.println(customer.getId()); // 这时c对象有ODI值,没有被session管理了,这时c对象是脱管态
    }
}


1、瞬时态 (Transient)
当我们通过Java的new关键字来生成一个实体对象时,这时这个实体对象就处于自由状态。
此时的对象只是通过JVM获得了一块内存空间,还并没有通过Session对象的save()方法保存进数据库,因此也就还没有纳入Hibernate的缓存管理中,也就是说对象现在还自由的游荡于Hibernate缓存管理之外。所以我们可以看出自由对象最大的特点就是,在数据库中不存在一条与它对应的记录。 


2、持久状态 (Persistent)
持久化对象就是已经被保存进数据库的实体对象(除了尚未提交的记录),并且这个实体对象现在还处于Hibernate的session缓存管理之中。 这时对该实体对象的任何修改,都会在清理缓存时同步到数据库中。
/**
 * 测试持久态的对象自动同步
 */
@Test
public void testPersistentStatus(){

    Session session = HibernateUtil.openSession();
    Transaction tx = session.beginTransaction();

    //获取到一个持久态对象
    Customer customer = new Customer();
    customer.setName("老王");
    session.save(customer);

    //修改customer的数据
    customer.setName("汤姆");

    //没有必要执行update语句,因为现在持久态对象能够更新数据库的数据啦!
    //session.update(customer);

    tx.commit();//事务提交时自动执行update方法
    session.close();
}

这时我们并没有显示调用session.update()方法来保存更新,但是对实体对象的修改还是会同步更新到数据库中,因为此时customer对象通过save方法保存进数据库后,已经是持久化对象了,所以它还处于Hibernate缓存的管理之中,这时当执行tx.commit()方法时,Hibernate会自动清理缓存,并且自动将持久化对象的属性变化同步到到数据库中。

持久的实例在数据库中有对应的记录,并拥有一个持久化标识 (identifier).

持久对象总是与 Session 和 Transaction 相关联,在一个 Session 中,对持久对象的改变不会马上对数据库进行变更,而必须在 Transaction 终止,也就是执行 commit() 之后,才在数据库中真正运行 SQL 进行变更,持久对象的状态才会与数据库进行同步。 在同步之前的持久对象称为脏 (dirty) 对象。


3、脱管状态 (Detached)
当一个持久化对象,脱离开Hibernate的缓存管理后(简单地理解就是 session关闭后),它就处于游离状态,游离对象和自由对象的最大区别在于,游离对象在数据库中可能还存在一条与它对应的记录,只是现在这个游离对象脱离了Hibernate的缓存管理。

三、对象的状态切换

下面的图表示了一个Hibernate管理的对象从产生到消亡的生命周期以及在生命周期内的状态转换



误区1、没有id值,就是瞬时状态,有id不在session范围内就是脱管状态。
从上面的解释来看,瞬时状态变为脱管状态,只要加上id就行了,但是从状态图来说,瞬时状态不能直接变为游离状态,而游离状态可以通过delete直接到达瞬时状态(其实说直接,也是先将游离状态的对象加入到session缓存中变为持久状态,然后delete,再变为瞬时状态而已)。
那么上面所用的通过有没有id值来判断三种状态就是有偏差的,可以这么理解,瞬时状态在数据库中就一定没有对应的记录,而游离状态一定是通过持久状态转变而来的,并且在数据库中可能有记录(没有记录是因为多线程,有别的程序把那条记录给删除了,所以一般就觉得是有记录的),所以瞬时状态和游离状态的区分点就在:从什么转变而来的,如果直接new的,那么就是瞬时状态对象,如果从持久态转变的,那么就是游离状态。 
误区2:识别是不是持久化状态,是看在session缓存内,还有就是在数据库中有记录。
这里的前半句对,但是后半句不准确,持久状态可能在数据库中有记录,也可能在数据库中没有记录。
说说没有记录的时候:当session.save保存瞬时状态时,事务还没有提交,对象还只是在session的一级缓存中,数据库中就没有该记录,但此时它就已经是持久状态对象了。
误区3:认为session一操作,就会发出sql语句,这个上面已经说明白了,应该很清楚了
小总结一下:怎么区分这三种状态
1、如果是在session缓存中,那么就一定是持久状态
2、如果是刚new出来的对象,那么就肯定是瞬时状态
3、如果是从session缓存中出来的,也就是通过一些session.clear、ecivt等操作,清除了缓存的,那么就是游离状态,

只有瞬时状态能确定数据库中没有对应记录,其他两个状态,都是不确定数据库中是否有对应记录
一切都以官方给出的图为准,其他的快速识别状态的方法,都是不可取的,自己还是没弄明白其中的道理,也就永远没把握自己是不是对的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值