您好,登錄后才能下訂單哦!
本篇內容主要講解“Hibernate緩存機制的原理”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Hibernate緩存機制的原理”吧!
Hibernate是一個持久層框架,經常訪問物理數據庫。
為了降低應用程序對物理數據源訪問的頻次,從而提高應用程序的運行性能。
緩存內的數據是對物理數據源中的數據的復制,應用程序在運行時從緩存讀寫數據,在特定的時刻或事件會同步緩存和物理數據源的數據。
回到頂部
當 Session 對象調用 save() 方法保存一個對象后,該對象會被放入到 Session 緩存中。
當 Session 對象調用 get() 或 load() 方法從數據庫取出一個對象后,該對象也會被放入到 Session 緩存中。
當使用同一個 Session 編寫 HQL 和 QBC 等從數據庫中查詢數據時,將直接從緩存中讀取數據,不會訪問數據庫。
Hibernate 提供了幾個方法(evit/clear/contains/flush....)來管理和判斷一級緩存。
現 JavaEE Dao 層中,提供給外部的數據庫訪問,每次都會從 Session 工廠中獲取新的 Session 線程 ,導致一級緩存很少被利用。
實例項目源碼:https://git.oschina.net/LanboEx/hiberdemo
//1.Hibernate 自身的一級緩存,可以查看到只輸出了一條 sql Session session = getSession(); UserPO userPO = session.get(UserPO.class, "031e7a36972e11e6acede16e8241c0fe"); System.out.println("1. 第一次訪問 DB:" + userPO.getName() + "," + userPO.getPasswd()); UserPO userPO1 = session.get(UserPO.class, "031e7a36972e11e6acede16e8241c0fe"); System.out.println("2. 第二次訪問 DB:" + userPO1.getName() + ",一級緩存中是否存在特定對象" + session.contains(userPO));
//2.使用 evite/clear 方法手動清除緩存中特定對象,可以看到 hiber 輸出了兩條 SQL Session session1 = getSession(); UserPO userPO3 = session1.get(UserPO.class, "031e7a36972e11e6acede16e8241c0fe"); System.out.println("3. 第一次獲取對象:" + userPO3.getName() + "," + userPO3.getPasswd()); session1.evict(userPO3); UserPO userPO4 = session1.get(UserPO.class, "031e7a36972e11e6acede16e8241c0fe"); System.out.println("4. 第二次獲取對象:" + userPO4.getName() + "," + userPO4.getPasswd());
回到頂部
Hibernate 緩存包括兩大類:
a.Hibernate 一級緩存,又稱為[Session的緩存]。
Session 內置不能被卸載,Session 的緩存是事務范圍的緩存(Session 對象的生命周期通常對應一個數據庫事務或者一個應用事務)。
一級緩存中,持久化類的每個實例都具有唯一的 OID。
b.Hibernate 二級緩存,又稱為[SessionFactory的緩存]。
由于 SessionFactory 對象的生命周期和應用程序的整個過程對應。
Hibernate二級緩存是進程范圍或者集群范圍的緩存,有可能出現并發問題,需要采用適當的并發訪問策略,該策略為被緩存的數據提供了事務隔離級別。
第二級緩存是可選的,是一個可配置的插件,默認下 SessionFactory 不會啟用這個插件。
Hibernate 提供了 org.hibernate.cache.CacheProvider 接口,它充當緩存插件與 Hibernate 之間的適配器。
什么樣的數據適合存放到第二級緩存中?
1) 很少被修改的數據
2) 不是很重要的數據,允許出現偶爾并發的數據
3) 不會被并發訪問的數據
4) 常量數據
不適合存放到第二級緩存的數據?
1) 經常被修改的數據
2) 絕對不允許出現并發訪問的數據,如財務數據,絕對不允許出現并發
3) 與其他應用共享的數據。
c.Session 的延遲加載實現要解決兩個問題:正常關閉連接和確保請求中訪問的是同一個 Session。
Hibernate Session 就是 java.sql.Connection 的一層高級封裝,一個 Session 對應了一個 Connection。
Http 請求結束后正確的關閉 Session(過濾器實現了Session的正常關閉);
延遲加載必須保證是同一個 Session( Session 綁定在 ThreadLocal)。
d.Hibernate 查找對象如何應用緩存?
當 Hibernate 根據 ID 訪問數據對象的時候,首先從 Session 一級緩存中查;
查不到,如果配置了二級緩存,那么從二級緩存中查;
如果都查不到,再查詢數據庫,把結果按照 ID 放入到緩存刪除、更新、增加數據的時候,同時更新緩存。
e.一級緩存與二級緩存的對比圖
一級緩存 | 二級緩存 | |
存放數據的形式 | 相互關聯的持久化對象 | 對象的散裝數據 |
緩存的范圍 | 事務范圍,每個事務都擁有單獨的一級緩存 | 進程范圍或集群范圍,緩存被同一個進程或集群范圍內所有事務共享 |
并發訪問策略 | 由于每個事務都擁有單獨的一級緩存不會出現并發問題,因此無須提供并發訪問策略 | 由于多個事務會同時訪問二級緩存中的相同數據,因此必須提供適當的并發訪問策略,來保證特定的事務隔離級別 |
數據過期策略 | 處于一級緩存中的對象永遠不會過期,除非應用程序顯示清空或者清空特定對象 | 必須提供數據過期策略,如基于內存的緩存中對象的最大數目,允許對象處于緩存中的最長時間,以及允許對象處于緩存中的最長空閑時間 |
物理介質 | 內存 | 內存和硬盤,對象的散裝數據首先存放到基于內存的緩存中,當內存中對象的數目達到數據過期策略的maxElementsInMemory值,就會把其余的對象寫入基于硬盤的緩存中 |
緩存軟件實現 | 在Hibernate的Session的實現中包含 | 由第三方提供,Hibernate僅提供了緩存適配器,用于把特定的緩存插件集成到Hibernate中 |
啟用緩存的方式 | 只要通過Session接口來執行保存,更新,刪除,加載,查詢,Hibernate就會啟用一級緩存,對于批量操作,如不希望啟用一級緩存,直接通過JDBCAPI來執行 | 用戶可以再單個類或類的單個集合的粒度上配置第二級緩存,如果類的實例被經常讀,但很少被修改,就可以考慮使用二級緩存,只有為某個類或集合配置了二級緩存,Hibernate在運行時才會把它的實例加入到二級緩存中 |
用戶管理緩存的方式 | 一級緩存的物理介質為內存,由于內存的容量有限,必須通過恰當的檢索策略和檢索方式來限制加載對象的數目,Session的evit()方法可以顯示的清空緩存中特定對象,但不推薦 | 二級緩存的物理介質可以使內存和硬盤,因此第二級緩存可以存放大容量的數據,數據過期策略的maxElementsInMemory屬性可以控制內存中的對象數目,管理二級緩存主要包括兩個方面:選擇需要使用第二級緩存的持久化類,設置合適的并發訪問策略;選擇緩存適配器,設置合適的數據過期策略。SessionFactory的evit()方法也可以顯示的清空緩存中特定對象,但不推薦 |
到此,相信大家對“Hibernate緩存機制的原理”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。