hibernate缓存机制详解



 1.前言

在hibernate中有三级缓存,本篇博客先详细的介绍一下,Hibernate中的一级缓存,也就是Session级别的缓存。


 2.持久化对象

如果要说到Hibernate的缓存的话,那么首先咱得提一下hibernate中的持久化对象。

其中持久化对象有三种状态,分别是:

transient(瞬时态):尚未与Session关联对象,失去引用的话,就会被JVM回收。一般就是直接New创建的对象。

persistent(持久态):已经与当前session产生关联,并且相关联的session没有关闭,并且事务尚未提交。

detached(脱管态):存在持久化OID,但没有与当前session关联,脱管状态改变hibernate不能检测到。

[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">// 获得Session  
  2.         Session session = HibernateUtils.openSession();  
  3.         // 开启事务  
  4.         Transaction transaction = session.beginTransaction();  
  5.   
  6.         Book book = new Book(); // 瞬时态(没有OID,未与Session关联)  
  7.         book.setName("hibernate精通");  
  8.         book.setPrice(56d);  
  9.   
  10.         session.save(book);// 持久态(具有OID,与Session关联)  
  11.   
  12.         // 提交事务,关闭Session  
  13.         transaction.commit();  
  14.         session.close();  
  15.   
  16.         System.out.println(book.getId()); // 脱管态(具有 OID,与Session断开关联)  
  17.   


 3.持久化对象之间转变

1.瞬态对象——通过new关键字获取

瞬时——持久:save、saveOrUpdate(都是通过session获得)

瞬时——脱管:对象.setID(1);为瞬时对象设置新的OID

2.持久化对象——通过get/load、Query查询获得

持久——瞬时:delete(被删除持久化对象,不建议再次使用)

持久——脱管:evict(清楚一级缓存中某个对象)、close(关闭Session,清除一级缓存)、clear(清楚一级缓存所有对象)

3.脱管对象:无法直接获得

脱管——瞬时:对象.setID(null);删除对象OID

脱管——持久:update、saveOrUpdate、lock


 4.Session中的一级缓存

终于到本篇博客的重点了,其中Session的缓存是通过集合来实现的,在hibernate中封装了list和map的各种集合,用来为Session服务。

hibernate缓存机制详解_第1张图片


分析:hibernate向一级缓存放入数据时,同时保存快照数据,当修改一级缓存的时候,在flush操作时,对比缓存和快照,如果不一致,自动更新。


常见的操作

1.flush

修改一级缓存数据,针对内存操作,需要在session执行flush操作时,将缓存变化同步在数据库,而只有在缓存数据与快照区不一致的时候,才会生成update语句。

[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">@Test  
  2.     public void fun7() {  
  3.         // 通过工具类获取session值  
  4.         Session session = HibernateUtils.getSession();  
  5.         // 启动事务操作  
  6.         session.beginTransaction();  
  7.   
  8.         // session.setFlushMode(FlushMode.MANUAL);  
  9.   
  10.         // 通过ID从数据库中获取值,此时会产生快照  
  11.         Book book1 = (Book) session.get(Book.class1);  
  12.         // 修改属性值  
  13.         book1.setName("struts璇﹁В");  
  14.         // 手动flush,刷新缓存到数据库,此时只是生成SQL语句,但是数据库中并没有发生变化,只有commit后,数据库才会发生相应的变化。  
  15.         session.flush();  
  16.         // 手动提交事务  
  17.         session.getTransaction().commit();  
  18.         // 关闭session的资源  
  19.         session.close();  
  20.     }  


2.clear

清楚所有对象的一级缓存,对对象所做的修改,全部都没有了,跟当初的快照一样。

[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">public void fun7() {  
  2.         // 通过工具类获取session值  
  3.         Session session = HibernateUtils.getSession();  
  4.         // 启动事务操作  
  5.         session.beginTransaction();  
  6.   
  7.         // session.setFlushMode(FlushMode.MANUAL);  
  8.   
  9.         // 通过ID从数据库中获取值,此时会产生快照  
  10.         Book book1 = (Book) session.get(Book.class1);  
  11.         // 修改属性值  
  12.         book1.setName("struts璇﹁В");  
  13.         //清除一级缓存操作,此时当作事务提交的时候,数据库中并没有发生任何的变化  
  14.         session.clear();  
  15.         // 手动提交事务  
  16.         session.getTransaction().commit();  
  17.         // 关闭session的资源  
  18.         session.close();  
  19.     }  
  20.   

3.evict

清除一级缓存指定对象

[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">@Test  
  2.     public void fun5() {  
  3.           
  4.         Session session = HibernateUtils.getSession();  
  5.           
  6.         session.beginTransaction();  
  7.   
  8.         //当执行一次操作后,会把对象放置到Session缓存中  
  9.         Book book1 = (Book) session.get(Book.class1);  
  10.         Book book2 = (Book) session.get(Book.class2);  
  11.   
  12.   
  13.   
  14.         session.evict(book2); // 从缓存中清楚book2对象所做的修改  
  15.         // 当再次执行操作时,book2还会发出SQL语句操作  
  16.         Book book11 = (Book) session.get(Book.class1);   
  17.         Book book22 = (Book) session.get(Book.class2);  
  18.   
  19.         // 手动提交事务  
  20.         session.getTransaction().commit();  
  21.         // 关闭资源  
  22.         session.close();  
  23.     }  
  24.   

4.refresh

重新查询数据库,更新快照和一级缓存




[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">@Test  
  2.     public void fun6() {  
  3.           
  4.         Session session = HibernateUtils.getSession();  
  5.           
  6.         session.beginTransaction();  
  7.   
  8.         // 从数据库中查询book,并放置到Session缓存中一份  
  9.           
  10.         Book book1 = (Book) session.get(Book.class1);   
  11.         //修改缓存对象的值  
  12.         book1.setName("spring璇﹁В");   
  13.   
  14.         //又进行了一次查询操作,此时把快照中的数据与数据库一致  
  15.         session.refresh(book1);  
  16.   
  17.         System.out.println(book1);  
  18.   
  19.         // 4.鎻愪氦  
  20.         session.getTransaction().commit();  
  21.         // 5.閲婃斁璧勬簮  
  22.         session.close();  
  23.     }  


 5.Session手动控制缓存

在hibernate中也为 我们提供了手动控制缓存的机制,具体如下

Always:每次查询时,session都会flush

Auto:有些查询时,session会默认flush,例如commit。session.flush

Commit:在事务提交的时候

Manual:只有手动调用sessionflush才会刷出

[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">public void fun7() {  
  2.         // 通过工具类获取session值  
  3.         Session session = HibernateUtils.getSession();  
  4.         // 启动事务操作  
  5.         session.beginTransaction();  
  6.   
  7.          session.setFlushMode(FlushMode.MANUAL);  
  8.   
  9.         // 通过ID从数据库中获取值,此时会产生快照  
  10.         Book book1 = (Book) session.get(Book.class1);  
  11.         // 修改属性值  
  12.         book1.setName("struts璇﹁В");  
  13.         //因为上面开启了,手动提交缓存,所以只有手动提交,才能同步到数据库操作  
  14.         session.flush();  
  15.         // 手动提交事务  
  16.         session.getTransaction().commit();  
  17.         // 关闭session的资源  
  18.         session.close();  
  19.     }  
  20.  

 1.前言

在hibernate中有三级缓存,本篇博客先详细的介绍一下,Hibernate中的一级缓存,也就是Session级别的缓存。


 2.持久化对象

如果要说到Hibernate的缓存的话,那么首先咱得提一下hibernate中的持久化对象。

其中持久化对象有三种状态,分别是:

transient(瞬时态):尚未与Session关联对象,失去引用的话,就会被JVM回收。一般就是直接New创建的对象。

persistent(持久态):已经与当前session产生关联,并且相关联的session没有关闭,并且事务尚未提交。

detached(脱管态):存在持久化OID,但没有与当前session关联,脱管状态改变hibernate不能检测到。

[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">// 获得Session  
  2.         Session session = HibernateUtils.openSession();  
  3.         // 开启事务  
  4.         Transaction transaction = session.beginTransaction();  
  5.   
  6.         Book book = new Book(); // 瞬时态(没有OID,未与Session关联)  
  7.         book.setName("hibernate精通");  
  8.         book.setPrice(56d);  
  9.   
  10.         session.save(book);// 持久态(具有OID,与Session关联)  
  11.   
  12.         // 提交事务,关闭Session  
  13.         transaction.commit();  
  14.         session.close();  
  15.   
  16.         System.out.println(book.getId()); // 脱管态(具有 OID,与Session断开关联)  
  17.   


 3.持久化对象之间转变

1.瞬态对象——通过new关键字获取

瞬时——持久:save、saveOrUpdate(都是通过session获得)

瞬时——脱管:对象.setID(1);为瞬时对象设置新的OID

2.持久化对象——通过get/load、Query查询获得

持久——瞬时:delete(被删除持久化对象,不建议再次使用)

持久——脱管:evict(清楚一级缓存中某个对象)、close(关闭Session,清除一级缓存)、clear(清楚一级缓存所有对象)

3.脱管对象:无法直接获得

脱管——瞬时:对象.setID(null);删除对象OID

脱管——持久:update、saveOrUpdate、lock


 4.Session中的一级缓存

终于到本篇博客的重点了,其中Session的缓存是通过集合来实现的,在hibernate中封装了list和map的各种集合,用来为Session服务。

hibernate缓存机制详解_第2张图片


分析:hibernate向一级缓存放入数据时,同时保存快照数据,当修改一级缓存的时候,在flush操作时,对比缓存和快照,如果不一致,自动更新。


常见的操作

1.flush

修改一级缓存数据,针对内存操作,需要在session执行flush操作时,将缓存变化同步在数据库,而只有在缓存数据与快照区不一致的时候,才会生成update语句。

[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">@Test  
  2.     public void fun7() {  
  3.         // 通过工具类获取session值  
  4.         Session session = HibernateUtils.getSession();  
  5.         // 启动事务操作  
  6.         session.beginTransaction();  
  7.   
  8.         // session.setFlushMode(FlushMode.MANUAL);  
  9.   
  10.         // 通过ID从数据库中获取值,此时会产生快照  
  11.         Book book1 = (Book) session.get(Book.class1);  
  12.         // 修改属性值  
  13.         book1.setName("struts璇﹁В");  
  14.         // 手动flush,刷新缓存到数据库,此时只是生成SQL语句,但是数据库中并没有发生变化,只有commit后,数据库才会发生相应的变化。  
  15.         session.flush();  
  16.         // 手动提交事务  
  17.         session.getTransaction().commit();  
  18.         // 关闭session的资源  
  19.         session.close();  
  20.     }  


2.clear

清楚所有对象的一级缓存,对对象所做的修改,全部都没有了,跟当初的快照一样。

[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">public void fun7() {  
  2.         // 通过工具类获取session值  
  3.         Session session = HibernateUtils.getSession();  
  4.         // 启动事务操作  
  5.         session.beginTransaction();  
  6.   
  7.         // session.setFlushMode(FlushMode.MANUAL);  
  8.   
  9.         // 通过ID从数据库中获取值,此时会产生快照  
  10.         Book book1 = (Book) session.get(Book.class1);  
  11.         // 修改属性值  
  12.         book1.setName("struts璇﹁В");  
  13.         //清除一级缓存操作,此时当作事务提交的时候,数据库中并没有发生任何的变化  
  14.         session.clear();  
  15.         // 手动提交事务  
  16.         session.getTransaction().commit();  
  17.         // 关闭session的资源  
  18.         session.close();  
  19.     }  
  20.   

3.evict

清除一级缓存指定对象

[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">@Test  
  2.     public void fun5() {  
  3.           
  4.         Session session = HibernateUtils.getSession();  
  5.           
  6.         session.beginTransaction();  
  7.   
  8.         //当执行一次操作后,会把对象放置到Session缓存中  
  9.         Book book1 = (Book) session.get(Book.class1);  
  10.         Book book2 = (Book) session.get(Book.class2);  
  11.   
  12.   
  13.   
  14.         session.evict(book2); // 从缓存中清楚book2对象所做的修改  
  15.         // 当再次执行操作时,book2还会发出SQL语句操作  
  16.         Book book11 = (Book) session.get(Book.class1);   
  17.         Book book22 = (Book) session.get(Book.class2);  
  18.   
  19.         // 手动提交事务  
  20.         session.getTransaction().commit();  
  21.         // 关闭资源  
  22.         session.close();  
  23.     }  
  24.   

4.refresh

重新查询数据库,更新快照和一级缓存




[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">@Test  
  2.     public void fun6() {  
  3.           
  4.         Session session = HibernateUtils.getSession();  
  5.           
  6.         session.beginTransaction();  
  7.   
  8.         // 从数据库中查询book,并放置到Session缓存中一份  
  9.           
  10.         Book book1 = (Book) session.get(Book.class1);   
  11.         //修改缓存对象的值  
  12.         book1.setName("spring璇﹁В");   
  13.   
  14.         //又进行了一次查询操作,此时把快照中的数据与数据库一致  
  15.         session.refresh(book1);  
  16.   
  17.         System.out.println(book1);  
  18.   
  19.         // 4.鎻愪氦  
  20.         session.getTransaction().commit();  
  21.         // 5.閲婃斁璧勬簮  
  22.         session.close();  
  23.     }  


 5.Session手动控制缓存

在hibernate中也为 我们提供了手动控制缓存的机制,具体如下

Always:每次查询时,session都会flush

Auto:有些查询时,session会默认flush,例如commit。session.flush

Commit:在事务提交的时候

Manual:只有手动调用sessionflush才会刷出

[java]  view plain  copy
 print ?
  1. "font-family:SimSun;font-size:18px;">public void fun7() {  
  2.         // 通过工具类获取session值  
  3.         Session session = HibernateUtils.getSession();  
  4.         // 启动事务操作  
  5.         session.beginTransaction();  
  6.   
  7.          session.setFlushMode(FlushMode.MANUAL);  
  8.   
  9.         // 通过ID从数据库中获取值,此时会产生快照  
  10.         Book book1 = (Book) session.get(Book.class1);  
  11.         // 修改属性值  
  12.         book1.setName("struts璇﹁В");  
  13.         //因为上面开启了,手动提交缓存,所以只有手动提交,才能同步到数据库操作  
  14.         session.flush();  
  15.         // 手动提交事务  
  16.         session.getTransaction().commit();  
  17.         // 关闭session的资源  
  18.         session.close();  
  19.     }  
  20.  

你可能感兴趣的:(JAVA)