Hibernate二级缓存——SessionFactory
Hibernate二級緩存簡介
在《Hibernate一級緩存——Session》中介紹了Session級別的一級緩存,例如,當如下的代碼執行時,由于一級緩存的作用,只會發送一條select語句:
@Testpublic void testCache(){Employee employee1 = (Employee) session.get(Employee.class, 1);System.out.println(employee1);Employee employee2 = (Employee) session.get(Employee.class, 1);System.out.println(employee2);}現在,我們在兩次加載代碼之間,先關閉當前的session和事務,再重新開啟一個session和事務,那么不難理解,由于開啟了新的session,所以會打印兩條select語句:
@Testpublic void testCache(){Employee employee1 = (Employee) session.get(Employee.class, 1);System.out.println(employee1);//提交事務,關sessiontransaction.commit();session.close();//開啟一個新的session和事務session = sessionFactory.openSession();transaction = session.beginTransaction();Employee employee2 = (Employee) session.get(Employee.class, 1);System.out.println(employee2);}
那么,有沒有辦法使就算session關閉,也能緩存employee對象的辦法呢?這就是我們現在要介紹的,SessionFactory級別的,Hibernate二級緩存。
緩存(Cache )是計算機領域非常通用的概念。它介于應用程序和永久性數據存儲源(如硬盤上的文件或者數據庫)之間,其作用是降低應用程序直接讀寫永久性數據存儲源的頻率,從而提高應用的運行性能。緩存中的數據是數據存儲源中數據的拷貝,應用程序在運行時直接讀寫緩存中的數據,只在某些特定時刻按照緩存中的數據來同步更新數據存儲源。緩存的物理介質通常是內存。
Hibernate中提供了兩個級別的緩存:
1.第一級別的緩存是Session級別的緩存,它是屬于事務范圍的緩存,即緩存只能被當前事務訪問,每個事務都有獨自的緩存。緩存的生命周期依賴于事務的生命周期,當事務結束時,緩存也就結束生命周期。在此范圍下,緩存的介質是內存。這一級別的緩存是由hibernate管理的,一般情況下無須進行干預。
2.第二級別的緩存是SessionFactory級別的緩存,它是屬于進程范圍的緩存。緩存被進程內的所有事務共享。這些事務有可能是并發訪問緩存,因此必須對緩存采取必要的事務隔離機制。緩存的生命周期依賴于進程的生命周期,進程結束時,緩存也就結束了生命周期。進程范圍的緩存可能會存放大量的數據,所以存放的介質可以是內存或硬盤。這一級別的緩存可以進行配置和更改,并且可以動態加載和卸載。
SessionFactory 的緩存可以分為兩類:
內置緩存: Hibernate自帶的,不可卸載。通常在Hibernate的初始化階段,Hibernate會把映射元數據和預定義的SQL語句放到SessionFactory的緩存中,映射元數據是映射文件中數據的復制,而預定義SQL語句是Hibernate根據映射元數據推到出來的。該內置緩存是只讀的。
外置緩存(二級緩存):一個可配置的緩存插件。在默認情況下,SessionFactory不會啟用這個緩存插件。外置緩存中的數據是數據庫中數據的復制,外置緩存的物理介質可以是內存,也可以是硬盤。
緩存的物理介質通常是內存,而永久性數據存儲源的物理介質通常是硬盤或磁盤,應用程序讀寫內在的速度顯然比讀寫硬盤的速度快,如果緩存中存放的數據量非常大,也會用硬盤作為緩存的物理介質。緩存的實現不僅需要作為物理介質的硬件,同時還需要用于管理緩存的并發訪問和過期等策略的軟件。因此,緩存是通過軟件和硬件共同實現的。
適合放入二級緩存中的數據:
1.很少被修改;
2.不是很重要的數據,允許出現偶爾的并發問題。
不適合放入二級緩存中的數據:
1.經常被修改;
2.財務數據,絕對不允許出現并發問題;
3.與其他應用程序共享的數據。
二級緩存的并發訪問策略:
兩個并發的事務同時訪問持久層的緩存的相同數據時,也有可能出現各類并發問題。
二級緩存可以設定以下4種類型的并發訪問策略,每一種訪問策略對應一種事務隔離級別。
非嚴格讀寫(Nonstrict-read-write):不保證緩存與數據庫種數據的一致性。提供read uncommitted事務隔離級別。對于極少被修改,而且允許臟讀的數據,可以采用這種策略。
讀寫型(Read-write):提供read committed事務隔離級別。對于經常讀但是很少被修改的數據,可以采用這種隔離類型,它可以防止臟讀。(通常選用的策略)
事務型(Transactional):僅在受管理環境下適用。它提供了repeatable read的事務隔離級別。對于經常讀,但是很少被修改的數據,可以采用這種隔離類型,它可以防止臟讀和不可重復讀。
只讀型(Read-Only):提供serializable事務隔離級別,對于從來不會修改的數據,可以采用這種訪問策略,可以避免臟讀,不可重復讀和幻讀。
管理Hibernate的二級緩存:
Hibernate的二級緩存是進程或者集群范圍內的緩存。
二級緩存是可配置的插件,Hibernate允許選用以下類型的緩存插件:
EhCache:可作為進程范圍的緩存,存放數據的物理介質可以是內存或硬盤,對Hibernate的查詢緩存提供了支持。
OSCache:可作為進程范圍的緩存,存放數據的物理介質可以是內存或硬盤,提供了豐富的緩存數據過期策略,對Hibernate的查詢緩存提供了支持。
SwarmCache:可作為群集范圍內的緩存,但不支持Hibernate的查詢緩存。 JBossCache:可作為群集范圍內的緩存,支持事務型并發訪問策略,對Hibernate的查詢緩存提供了支持。
使用Hibernate二級緩存的步驟
一、加入二級緩存的jar包及配置文件
1.加入jar包
2.添加配置文件ehcache.xml到src目錄下
二、配置hibernate.cfg.xml
1.配置啟用hibernate的二級緩存
2.配置hibernate二級緩存使用的產品
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>3.配置對哪些類(或屬性)使用 hibernate 的二級緩存
第一種情況,類級別的二級緩存:(配置對Employee類使用二級緩存)
<class-cache usage="read-write" class="com.atguigu.hibernate.entities.Employee"/>第二種情況,集合級別的二級緩存:(配置對Department類中的Employee集合屬性emps使用二級緩存)
<collection-cache usage="read-write" collection="com.atguigu.hibernate.entities.Department.emps"/>注意,當配置對集合屬性使用二級緩存時,還需要對集合所屬的類,集合中元素的類型使用二級緩存,例如,對于上述集合屬性,則還需配置對Department類和Employee類使用二級緩存:(如果不對Employee類配置二級緩存,則會多出n條SQL語句,得不償失。因為這種情況下緩存的是一個一個的employee的id,當要使用到employee對象時,需要再根據id一條一條地去數據庫查詢記錄)
<class-cache usage="read-write" class="com.atguigu.hibernate.entities.Department"/> <class-cache usage="read-write" class="com.atguigu.hibernate.entities.Employee"/>另外,配置對哪些類(或屬性)使用二級緩存,還可以在映射文件中配置,例如:
類級別(在class節點下):
集合級別:(在department映射文件的set節點下)
<cache usage="read-write"/> 現在,測試上面的testCache方法,只會打印一條select語句:
對于集合的測試也是一樣,只會打印兩條select語句,一條用于查詢department,一條用于查詢employee:
二級緩存配置文件
下面使用一個修改過的二級緩存配置文件介紹其中各個屬性的作用:
<ehcache><!-- Sets the path to the directory where cache .data files are created.If the path is a Java System Property it is replaced byits value in the running VM.The following properties are translated:user.home - User's home directoryuser.dir - User's current working directoryjava.io.tmpdir - Default temp file path --><!-- 指定一個目錄:當 EHCache 把數據寫到硬盤上時, 將把數據寫到這個目錄下.--> <diskStore path="d:\\tempDirectory"/><!--Default Cache configuration. These will applied to caches programmatically created throughthe CacheManager.The following attributes are required for defaultCache:maxInMemory - Sets the maximum number of objects that will be created in memoryeternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the elementis never expired.timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only usedif the element is not eternal. Idle time is now - last accessed timetimeToLiveSeconds - Sets the time to live for an element before it expires. Is only usedif the element is not eternal. TTL is now - creation timeoverflowToDisk - Sets whether elements can overflow to disk when the in-memory cachehas reached the maxInMemory limit.--><!-- 設置緩存的默認數據過期策略 --> <defaultCache maxElementsInMemory="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="true"/><!-- 設定具體的命名緩存的數據過期策略。每個命名緩存代表一個緩存區域緩存區域(region):一個具有名稱的緩存塊,可以給每一個緩存塊設置不同的緩存策略。如果沒有設置任何的緩存區域,則所有被緩存的對象,都將使用默認的緩存策略。即:<defaultCache.../>Hibernate 在不同的緩存區域保存不同的類/集合。對于類而言,區域的名稱是類名。如:com.atguigu.domain.Customer對于集合而言,區域的名稱是類名加屬性名。如com.atguigu.domain.Customer.orders--><!-- name: 設置緩存的名字,它的取值為類的全限定名或類的集合的名字 maxElementsInMemory: 設置基于內存的緩存中可存放的對象最大數目 eternal: 設置對象是否為永久的, true表示永不過期,此時將忽略timeToIdleSeconds 和 timeToLiveSeconds屬性; 默認值是false timeToIdleSeconds:設置對象空閑最長時間,以秒為單位, 超過這個時間,對象過期。當對象過期時,EHCache會把它從緩存中清除。如果此值為0,表示對象可以無限期地處于空閑狀態。 timeToLiveSeconds:設置對象生存最長時間,超過這個時間,對象過期。如果此值為0,表示對象可以無限期地存在于緩存中. 該屬性值必須大于或等于 timeToIdleSeconds 屬性值 overflowToDisk:設置基于內存的緩存中的對象數目達到上限后,是否把溢出的對象寫到基于硬盤的緩存中 --><cache name="com.atguigu.hibernate.entities.Employee"maxElementsInMemory="1"eternal="false"timeToIdleSeconds="300"timeToLiveSeconds="600"overflowToDisk="true"/><cache name="com.atguigu.hibernate.entities.Department.emps"maxElementsInMemory="1000"eternal="true"timeToIdleSeconds="0"timeToLiveSeconds="0"overflowToDisk="false"/></ehcache>查詢緩存
對于經常使用的查詢語句,如果啟用了查詢緩存,當第一次執行查詢語句時,Hibernate會把查詢結果存放在查詢緩存中,以后再次執行該查詢語句時,只需從緩存中獲得查詢結果,從而提高查詢性能。
默認情況下,Hibernate設置的緩存對HQL和QBC查詢是無效的,但可以通過以下步驟使其有效:
1.配置二級緩存,因為查詢緩存依賴于二級緩存.
2.在hibernate配置文件中聲明開啟查詢緩存。
3.調用Query或者Criteria的setCachable(true)。
例如,在沒有配置查詢緩存的情況下,下面的代碼會打印兩條select語句:
進行了相關配置之后,并且在方法中設置query.setCacheable(true);則只會打印一條select語句:
查詢緩存適用于如下場合:
1.應用程序運行時經常使用查詢語句
2.很少對與查詢語句檢索到的數據進行插入,刪除或更新操作
時間戳緩存區域
時間戳緩存區域存放了對于查詢結果相關的表進行插入,更新或者刪除操作的時間戳。Hibernate通過時間戳緩存區域來判斷被緩存的查詢結果是否過期,其運行過程如下:
T1時刻執行查詢操作,把結果存放在QueryCache區域,記錄該區域的時間戳為T1;
T2時刻(可能在T1之前,也可能在T1之后)對查詢結果相關的表進行更新操作,Hibernate把T2時刻存放在UpdateTimestampCache區域。
T3時刻(在T1,T2之后)執行查詢結果前,先比較QueryCache區域的時間戳和UpdateTimestampCache區域的時間戳。若T2>T1,則丟棄原先存放在QueryCache區域的查詢結果,重新到數據庫中查詢數據并放入QueryCache區域;若T2
在第二次查詢的時候,會重新用select去數據庫中查找最新的記錄。
Query接口的iterate()方法
Query的list方法返回實體類對應表的所有字段,而Query的iterate方法僅返回數據包的ID字段。當使用了iterate方法,然后遍歷訪問結果集時,先到Session緩存及二級緩存中查看是否存在特定OID的對象,如果存在,直接返回,否則就通過相應的SQL SELECT語句到數據庫中查找特定的記錄。
在大多數情況下,應該考慮使用list方法執行查詢操作,iterate方法僅在下述情況下可以稍微提高查詢性能:
1.要查詢的數據表中包含大量字段;
2.啟用了二級緩存,且二級緩存中可能已經包含了待查詢的對象。
總結
以上是生活随笔為你收集整理的Hibernate二级缓存——SessionFactory的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows 本地搭建git仓库_wi
- 下一篇: 给新安装的RHEL8虚拟机 安装 vmw