緩存不止存在與程式中,電腦硬體乃至於生活中都存在緩存 目的:提高效率 比如IO流讀寫位元組,如果沒有緩存,讀一位元組寫一位元組,效率低下 hibernate中的一級緩存:提高操作資料庫的效率 示例: 抽取的工具類 package utils; import org.hibernate.Session; i ...
緩存不止存在與程式中,電腦硬體乃至於生活中都存在緩存
目的:提高效率
比如IO流讀寫位元組,如果沒有緩存,讀一位元組寫一位元組,效率低下
hibernate中的一級緩存:提高操作資料庫的效率
示例:
抽取的工具類
package utils; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtils { private static SessionFactory sf; static{ //1 創建,調用空參構造 Configuration conf = new Configuration().configure(); //2 根據配置信息,創建 SessionFactory對象 sf = conf.buildSessionFactory(); } //獲得session => 獲得全新session public static Session openSession(){ //3 獲得session Session session = sf.openSession(); return session; } //獲得session => 獲得與線程綁定的session public static Session getCurrentSession(){ //3 獲得session Session session = sf.getCurrentSession(); return session; } }View Code
測試類:
示例1:
package cache; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.Test; import domain.Customer; import utils.HibernateUtils; //測試一級緩存 public class Demo { @Test //證明一級緩存存在 public void fun1(){ //1 獲得session Session session = HibernateUtils.openSession(); //2 控制事務 Transaction tx = session.beginTransaction(); //3執行操作 Customer c1 = session.get(Customer.class, 1l); Customer c2 = session.get(Customer.class, 1l); Customer c3 = session.get(Customer.class, 1l); Customer c4 = session.get(Customer.class, 1l); Customer c5 = session.get(Customer.class, 1l); System.out.println(c3==c5);//true //4提交事務.關閉資源 tx.commit(); session.close();// 游離|托管 狀態, 有id , 沒有關聯 //結果(保證資料庫中存在主鍵為1的數據): //這裡調用了五次方法,但是只列印一次SQL語句 } }
原理:程式第一次調用get方法,hibernate發送SQL語句查詢資料庫,查詢結果以ResulySet對象返回,
hibernate再組裝成Customer(實體類對象),存入session緩存對象,對象返回給程式
第二次調用get方法,會先從緩存中查看是否存在id=1的Customer對象,如果有,直接返回緩存中的對象
多次調用原理相同
明顯地發現:這裡的緩存技術很好地提升了效率
示例2:
@Test // public void fun2(){ //1 獲得session Session session = HibernateUtils.openSession(); //2 控制事務 Transaction tx = session.beginTransaction(); //3執行操作 Customer c1 = session.get(Customer.class, 1l); c1.setCust_name("哈哈");//4提交事務.關閉資源 tx.commit(); session.close();// 游離|托管 狀態, 有id , 沒有關聯 }
引入了快照的概念
原理:
上邊的原理其實有省略,資料庫返回結果後,hibernate組裝的時候,其實組裝了兩個對象,
一個放入緩存中,一個放入快照,返回給程式的是緩存對象,程式第一次修改了緩存對象,事務提交,
這時候hibernate比較緩存中的對象和快照,如果有變化,會同步到資料庫中,沒有變化,什麼都不做
這裡就提高了效率,不會多次去資料庫查詢,只需要比對緩存中的對象,減少不必要地SQL查詢語句
示例3:
@Test //持久化狀態對象其實就是放入session緩存中的對象 public void fun3(){ //1 獲得session Session session = HibernateUtils.openSession(); //2 控制事務 Transaction tx = session.beginTransaction(); //3執行操作 Customer c1 = new Customer(); c1.setCust_id(1l);//托管|游離 session.update(c1);//c1被放入session緩存了 Customer c2 = session.get(Customer.class, 1l); //4提交事務.關閉資源 tx.commit(); session.close();// 游離|托管 狀態, 有id , 沒有關聯 }
這段代碼運行中,列印SQL的UPDATE語句
原因:緩存中不存在快照,c1放入session緩存中對比快照時候必然不一致,而c2這一句調用get方法後,依照上邊的原理,才會運行SQL的UPDATE語句
所以,這段代碼中真正使hibernate發送SQL語句的是c2這一行