1. 程式人生 > >hibernate二級快取攻略(第二天)

hibernate二級快取攻略(第二天)

查詢快取

首先需要配置

hibernate.cache.use_query_cache = true

 如果用ehcache,配置ehcache.xml,注意hibernate3.0以後不是net.sf的包名了

< cache name = " net.sf.hibernate.cache.StandardQueryCache "  
    maxElementsInMemory
= " 50 "  
    eternal
= " false "  
    timeToIdleSeconds
= " 3600 "  
    timeToLiveSeconds
= " 7200 "  
    overflowToDisk
= " true "
/>
< cache name = " net.sf.hibernate.cache.UpdateTimestampsCache "  
    maxElementsInMemory
= " 5000 "  
    eternal
= " true "  
    overflowToDisk
= " true "
/>

然後

query.setCacheable( true ); // 啟用查詢快取  query.setCacheRegion( " myCacheRegion " ); // 指定要使用的cacheRegion,可選 

第二行指定要使用的cacheRegion是myCacheRegion,即你可以給每個查詢快取做一個單獨的配置,使用setCacheRegion來做這個指定,需要在ehcache.xml裡面配置它:

< cache name = " myCacheRegion "  
    maxElementsInMemory
= " 10 "  
    eternal
= " false "  
    timeToIdleSeconds
= " 3600 "  
    timeToLiveSeconds
= " 7200 "  
    overflowToDisk
= " true " />

如果省略第二行,不設定cacheRegion的話,那麼會使用上面提到的標準查詢快取的配置,也就是net.sf.hibernate.cache.StandardQueryCache

對於查詢快取來說,快取的key是根據hql生成的sql,再加上引數,分頁等資訊(可以通過日誌輸出看到,不過它的輸出不是很可讀,最好改一下它的程式碼)。

比如hql:

from Cat c where c.name like ?

生成大致如下的sql:

select * from cat c where c.name like ?

引數是"tiger%",那麼查詢快取的key*大約*是這樣的字串(我是憑記憶寫的,並不精確,不過看了也該明白了):

select * from cat c where c.name like ? , parameter:tiger%

這樣,保證了同樣的查詢、同樣的引數等條件下具有一樣的key。

現在說說快取的value,如果是list方式的話,value在這裡並不是整個結果集,而是查詢出來的這一串ID。也就是說,不管是list方法還是iterate方法,第一次查詢的時候,它們的查詢方式很它們平時的方式是一樣的,list執行一條sql,iterate執行1+N條,多出來的行為是它們填充了快取。但是到同樣條件第二次查詢的時候,就都和iterate的行為一樣了,根據快取的key去快取裡面查到了value,value是一串id,然後在到class的快取裡面去一個一個的load出來。這樣做是為了節約記憶體。

可以看出來,查詢快取需要開啟相關類的class快取。list和iterate方法第一次執行的時候,都是既填充查詢快取又填充class快取的。

這裡還有一個很容易被忽視的重要問題,即開啟查詢快取以後,即使是list方法也可能遇到1+N的問題!相同條件第一次list的時候,因為查詢快取中找不到,不管class快取是否存在資料,總是傳送一條sql語句到資料庫獲取全部資料,然後填充查詢快取和class快取。但是第二次執行的時候,問題就來了,如果你的class快取的超時時間比較短,現在class快取都超時了,但是查詢快取還在,那麼list方法在獲取id串以後,將會一個一個去資料庫load!因此,class快取的超時時間一定不能短於查詢快取設定的超時時間!如果還設定了發呆時間的話,保證class快取的發呆時間也大於查詢的快取的生存時間。這裡還有其他情況,比如class快取被程式強制evict了,這種情況就請自己注意了。

另外,如果hql查詢包含select字句,那麼查詢快取裡面的value就是整個結果集了。

當hibernate更新資料庫的時候,它怎麼知道更新哪些查詢快取呢?

hibernate在一個地方維護每個表的最後更新時間,其實也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的快取配置裡面。

當通過hibernate更新的時候,hibernate會知道這次更新影響了哪些表。然後它更新這些表的最後更新時間。每個快取都有一個生成時間和這個快取所查詢的表,當hibernate查詢一個快取是否存在的時候,如果快取存在,它還要取出快取的生成時間和這個快取所查詢的表,然後去查詢這些表的最後更新時間,如果有一個表在生成時間後更新過了,那麼這個快取是無效的。

可以看出,只要更新過一個表,那麼凡是涉及到這個表的查詢快取就失效了,因此查詢快取的命中率可能會比較低。

Collection快取

需要在hbm的collection裡面設定

<cache usage="read-write"/>

假如class是Cat,collection叫children,那麼ehcache裡面配置

<cache name="com.xxx.pojo.Cat.children"
maxElementsInMemory="20" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200"
overflowToDisk="true" />

Collection的快取和前面查詢快取的list一樣,也是隻保持一串id,但它不會因為這個表更新過就失效,一個collection快取僅在這個collection裡面的元素有增刪時才失效。

這樣有一個問題,如果你的collection是根據某個欄位排序的,當其中一個元素更新了該欄位時,導致順序改變時,collection快取裡面的順序沒有做更新。

快取策略

只讀快取(read-only):沒有什麼好說的

讀/寫快取(read-write):程式可能要的更新資料

不嚴格的讀/寫快取(nonstrict-read-write):需要更新資料,但是兩個事務更新同一條記錄的可能性很小,效能比讀寫快取好

事務快取(transactional):快取支援事務,發生異常的時候,快取也能夠回滾,只支援jta環境,這個我沒有怎麼研究過

讀寫快取和不嚴格讀寫快取在實現上的區別在於,讀寫快取更新快取的時候會把快取裡面的資料換成一個鎖,其他事務如果去取相應的快取資料,發現被鎖住了,然後就直接取資料庫查詢。

在hibernate2.1的ehcache實現中,如果鎖住部分快取的事務發生了異常,那麼快取會一直被鎖住,直到60秒後超時。

不嚴格讀寫快取不鎖定快取中的資料。

使用二級快取的前置條件

你的hibernate程式對資料庫有獨佔的寫訪問權,其他的程序更新了資料庫,hibernate是不可能知道的。你操作資料庫必需直接通過hibernate,如果你呼叫儲存過程,或者自己使用jdbc更新資料庫,hibernate也是不知道的。hibernate3.0的大批量更新和刪除是不更新二級快取的,但是據說3.1已經解決了這個問題。

這個限制相當的棘手,有時候hibernate做批量更新、刪除很慢,但是你卻不能自己寫jdbc來優化,很鬱悶吧。

SessionFactory也提供了移除快取的方法,你一定要自己寫一些JDBC的話,可以呼叫這些方法移除快取,這些方法是:
void evict(Class persistentClass)
Evict all entries from the second-level cache.
void evict(Class persistentClass, Serializable id)
Evict an entry from the second-level cache.
void evictCollection(String roleName)
Evict all entries from the second-level cache.
void evictCollection(String roleName, Serializable id)
Evict an entry from the second-level cache.
void evictQueries()
Evict any query result sets cached in the default query cache region.
void evictQueries(String cacheRegion)
Evict any query result sets cached in the named query cache region.

不過我不建議這樣做,因為這樣很難維護。比如你現在用JDBC批量更新了某個表,有3個查詢快取會用到這個表,用evictQueries(String cacheRegion)移除了3個查詢快取,然後用evict(Class persistentClass)移除了class快取,看上去好像完整了。不過哪天你添加了一個相關查詢快取,可能會忘記更新這裡的移除程式碼。如果你的jdbc程式碼到處都是,在你新增一個查詢快取的時候,還知道其他什麼地方也要做相應的改動嗎?

----------------------------------------------------

總結:

不要想當然的以為快取一定能提高效能,僅僅在你能夠駕馭它並且條件合適的情況下才是這樣的。hibernate的二級快取限制還是比較多的,不方便用jdbc可能會大大的降低更新效能。在不瞭解原理的情況下亂用,可能會有1+N的問題。不當的使用還可能導致讀出髒資料。

如果受不了hibernate的諸多限制,那麼還是自己在應用程式的層面上做快取吧。

在越高的層面上做快取,效果就會越好。就好像儘管磁碟有快取,資料庫還是要實現自己的快取,儘管資料庫有快取,咱們的應用程式還是要做快取。因為底層的快取它並不知道高層要用這些資料幹什麼,只能做的比較通用,而高層可以有針對性的實現快取,所以在更高的級別上做快取,效果也要好些吧。

相關推薦

hibernate二級快取(第二)

查詢快取 首先需要配置 hibernate.cache.use_query_cache = true  如果用ehcache,配置ehcache.xml,注意hibernate3.0以後不是net.sf的包名了 < cache name = " net.sf.

Hibernate 二級快取和查詢快取

一級快取:     1,在session上面有一個一級快取;一級快取的生命週期和session相同,一級快取最大生命週期就是一個執行緒;在web環境下面,session的最大生命週期就是一次請求;     2,一級快取可以用來幹嘛? &nb

Hibernate 二級快取的作用

使用快取,是需要對應用系統進行效能優化而常採用的一種重要手段。合理地運用快取,可以極大的提高應用系統的執行效率。 Hibernate中應用快取:因為應用程式訪問資料庫,讀寫資料的代價非常高,而利用持久層的快取可以減少應用程式與資料庫之間的互動,即把訪問過的資料儲存到快取中,應用程式再次訪問已經訪

Hibernate二級快取問題

相關概念和定義1、快取的意義把一些不常修改,但是又經常用的資料存放到記憶體中,這樣能減少與資料庫的互動,提升程式的效能 2、Hibernate中提供了兩級快取:第一級別的快取是Session級別的快取(比如說在呼叫get方法的時候,如果已經查詢過一次了,第二次就不會查了,而是直接返回session快取中已經

hibernate 二級快取和事務級別詳講

一、概述 這章總的分兩大塊來講解   第一大塊,hibernate的事務管理。對於hibernate的事務管理來說,如果之前學過資料庫的事務管理,那麼在這裡就順風順水了。如果沒學過,第一次遇到,那也沒關係,我會詳細解釋其中的內容。   第二大塊,hibernate的二級快取機制。這個看起

spring boot整合ehcache 2.x 用於hibernate二級快取

spring boot整合ehcache 2x 用於hibernate二級快取 專案依賴 Ehcache簡介 hibernate二級快取配置 ehcache配置檔案 ehcache事件監聽 註解方式使用二級快取 完整程式碼 本文將介紹如何在spring boot中整合ehcache作為hiberna

關於hibernate 二級快取 報錯問題

Maven   hibernate-ehcache 和hibernate-core版本需要一致 <dependency> <groupId>org.hibernate</groupId> <artifactId>h

2018年9月Python計算機二級複習

考試方式:   上機考試,考試時長 120 分鐘,滿分 100 分。   1. 題型及分值   單項選擇題 40 分( 含公共基礎知識部分 10 分)。   操作題 60 分( 包括基本程式設計題和綜合程式設計題)。   2. 考試環境   Windows 7 作業

Hibernate二級快取

Hibernate中沒有自己去實現二級快取,而是利用第三方的。簡單敘述一下配置過程,也作為自己以後用到的時候配置的一個參考。 1、我們需要加入額外的二級快取包,例如EHcache,將其包匯入。需要:ehcache-core-2.4.3.jar , hibernate-e

Hibernate二級快取實現的方式(在類中,在方法上實現的思路)

資料庫快取 - 幕布 資料庫快取兩種處理方式一種處理model,只查詢快取,不更新快取參考列子 使用者表的敏感詞列表思路專案pom檔案匯入hibernate-encache快取檔案建立

SSH開啟Hibernate二級快取

1、新增ehcache依賴: <!-- Hibernate二級快取依賴 --> <dependency> <groupId>org.hibernate</groupId> <artifac

Hibernate 二級快取-ehcache

1 新增依賴包 <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>

hibernate 二級快取

一、為什麼需要快取? 拉高程式效能 二、什麼樣的資料需要快取 很少被修改或根本不改的資料 業務場景比如:耗時較高的統計分析sql、電話賬單查詢sql等 三、 ehcache的特點 1 夠快 Ehcache的發行有一段時長了,經過幾年的努力和不計其數的效能測試,E

hibernate 二級快取和查詢快取原理和關係

一、hibernate的二級快取 如果開啟了二級快取,hibernate在執行任何一次查詢的之後,都會把得到的結果集放到快取中,快取結構可以看作是一個hash table,key是資料庫記錄的id,value是id對應的pojo物件。當用戶根據id查詢物件的時候(load、iterator方法),會首先在

hibernate二級快取 Ehcache配置詳解

一、hibernate快取簡介 一級快取(session):內部快取 事務範圍:快取只能被當前事務訪問。快取的生命週期依賴於事務的生命週期,當事務結束時,快取也就結束生命週期。 二級快取(sessionFactory): 快取被應用範圍內的所有事務共享。 這些事務

Hibernate二級快取以及ehcache的搭建配置

前言         這次主要複習Hibernate的二級快取的相關知識,配置以及使用。二級快取主要採用第三方的ehcache,也將介紹ehcache快取的相關配置屬性以及在專案中的搭建,具體的專案檢視下一篇的 Maven搭建SpringMVC+Hibernate專案詳解

hibernate二級快取機制

二級快取不像一級快取那樣預設開啟的,它需要配置。二級快取中的資料可適用範圍是當前應用的所有會話 在這些情況下面應該使用二級快取: 1.很少被修改的資料。如果經常修改的話要修改資料庫而且要修改快取裡面

hibernate二級快取測試

SessionFactory類: import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; imp

Hibernate二級快取併發說明

二級快取的策略        當多個併發的事務同時訪問持久化層的快取中的相同資料時,會引起併發問題,必須採用必要的事務隔離措施。        在程序範圍或叢集範圍的快取,即第二級快取,會出現併發問題。因此可以設定以下4種類型的併發訪問策略,每一種策略對應一種事務隔離級別。

Java程式設計師從笨鳥到菜鳥之(七十七)細談Hibernate(十九)Hibernate二級快取詳解

歡迎關注微信賬號:java那些事:csh624366188.每天一篇java相關的文章 java交流工作群1: 77800592(已滿) java交流學生群2:234897635(已滿) java交流工作群3:94507287 java交流工作群4: 272265434 我的郵箱: