Hibernate 持久化对象和一级缓存
关于如何手动创建Hibernate,Hibernate初了解已经介绍了,接下来了解持久化对象和一级缓存。
Hibernate的持久化类有三种状态:
1、Transient瞬时态:持久化对象没有唯一标识OID,没有纳入Session的管理。
2、Persistent持久态:持久化对象有唯一标识OID,已经纳入到Session的管理,另外,持久化具有自动更新数据库的特点
3、Detached脱管态:持久化对象有唯一标识OID,没有纳入到Session管理。
下面给出一段代码来区分这三种状态:
1 // 区分持久化对象的三种状态: 2 public void demo1(){ 3 // 1.创建Session 4 Session session = HibernateUtils.openSession(); 5 // 2.开启事务 6 Transaction tx = session.beginTransaction(); 7 8 // 向数据库中保存一本图书: 9 Book book = new Book(); // 瞬时态:没有唯一标识OID,没有与session关联. 10 book.setName("Hiernate开发"); 11 book.setAuthor("孙XX"); 12 book.setPrice(65d); 13 14 session.save(book); // 持久态:有唯一标识OID,与session关联. 15 16 // 3.事务提交 17 tx.commit(); 18 // 4.释放资源 19 session.close(); 20 21 book.setName("Struts2开发"); // 脱管态:有唯一的标识,没有与session关联. 22 }
另外,三种状态对象的转换如下:
瞬时态: 获得: Book book = new Book(); 瞬时--->持久 * save(book); * save()/saveOrUpdate(); 瞬时--->脱管 * book.setId(1); 持久态: 获得: Book book = (Book)session.get(Book.class,1); * get()/load()/find()/iterate(); 持久--->瞬时: * delete(book); * 特殊状态:删除态.(被删除的对象,不建议去使用.) 持久--->脱管: * session.close(); * close()/clear()/evict(); 脱管态: 获得: Book book = new Book(); book.setId(1); 脱管--->持久: * session.update(); * update()/saveOrUpdate()/lock() 脱管--->瞬时: * book.setId(null);
上面我们提到了持久化对象具有自动更新数据库的特点,其根本原因是依赖于hibernate的一级缓存。
在hibernate中,分成两个基本的缓存:
一级缓存和二级缓存,其实还有个缓存,名为查询缓存,也有书籍把其命名为三级缓存,下面我就先介绍一级缓存。
一级缓存:Session级别的缓存,一级缓存与session的生命周期一致,是自带的,不可卸载。
至于缓存的好处,无非提高效率。
演示:
1 // 证明一级缓存的存在 2 public void demo3(){ 3 // 1.创建Session 4 Session session = HibernateUtils.openSession(); 5 // 2.开启事务 6 Transaction tx = session.beginTransaction(); 7 8 // save方法可以向一级缓存中存放数据的. 9 /*Book book = new Book(); 10 book.setName("JQuery开发"); 11 book.setAuthor("张XX"); 12 book.setPrice(45d); 13 14 Integer id = (Integer) session.save(book); 15 16 Book book2 = (Book) session.get(Book.class, id); 17 18 System.out.println(book2);*/ 19 20 // 分别用get执行两次查询. 21 Book book1 = (Book) session.get(Book.class, 1);// 马上发生SQL去查询 22 System.out.println(book1); 23 24 Book book2 = (Book) session.get(Book.class, 1);// 不发生SQL,因为使用一级缓存的数据 25 System.out.println(book2); 26 27 // 3.提交事务 28 tx.commit(); 29 // 4.关闭资源 30 session.close();
当session加载了customer对象后,会为customer对象的值类型的属性复制一份快照,也就是在一级缓存中的快照区copy一份相同的数据。
当刷出缓存时,通过比较对象的当前属性和快照,来判断对象的哪些属性发生了变化,如果数据一致,不更新,如果数据不一致,自动更新数据库。
在hibernate中,我们可以通过一些方法来管理一级缓存:
一级缓存是与session的生命周期相关的.session生命周期结束,一级缓存销毁了.
clear() :清空一级缓存中所有的对象.
evict(Object obj) :清空一级缓存中某个对象.
flush() :刷出缓存.
refresh(Object obj):将快照区的数据重新覆盖了一级缓存的数据.
另外,关于一级缓存的刷出时机
FlushMode: * ALWAYS :每次查询的时候都会刷出.手动调用flush.事务提交的时候. * AUTO :默认值.有些查询会刷出.手动调用flush.事务提交的时候. * COMMIT :在事务提交的时候,手动调用flush的时候. * MANUAL :只有在手动调用flush才会刷出.
严格程度:MANUAL > COMMIT > AUTO > ALWAYS