一、性能优化策略
- 一级缓存和快照
- 延迟加载策略
- 抓取策略
- 使用连接池
- 二级缓存
要掌握这些性能优化策略,必须首先了解对象的三种状态
二、对象的三种状态
在 Hibernate 程序运行过程中,一个对象会存在以下的三种状态,分别为:
- 瞬时态: 没有对象 OID 值,没有被 session 管理
- 持久态:有对象 OID 值,已经被 session 管理
- 脱管态:有对象 OID 值,已经脱离 session 管理
处于持久态的对象也称为
PO(Persistence Object),瞬时对象和脱管对象也称为
VO(Value Object)。
这3个状态是hibernate里pojo对象得3个状态,
POJO(Plain Ordinary Java Object)简单的Java对象
测试三种状态:
|
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等操作,清除了缓存的,那么就是游离状态,
只有瞬时状态能确定数据库中没有对应记录,其他两个状态,都是不确定数据库中是否有对应记录
一切都以官方给出的图为准,其他的快速识别状态的方法,都是不可取的,自己还是没弄明白其中的道理,也就永远没把握自己是不是对的。