(1)一級緩存就是session級別的緩存,一個session做了一個查詢操作,它會把這個操作的結果放在一級緩存中,如果短時間內這個session(一定要同一個session)又做了同一個操作,那么hibernate直接從一級緩存中拿,而不會再去連數據庫,取數據;
(2)二級緩存就是sessionfactory級別的緩存,顧名思義,就是查詢的時候會把查詢結果緩存到二級緩存中,如果同一個sessionfactory創建的某個session執行了相同的操作,hibernate就會從二級緩存中拿結果,而不會再去連接數據庫;
(3)hibernate中提供了兩級cache,第一級別的緩存是session級別的緩存,它是屬于事務范圍的緩存。這一級別的緩存由hibernate管理的,一般情況下無需進行干預;第二級別的緩存是sessionfactory級別的緩存,它是屬于進程范圍或群集范圍的緩存。這一級別的緩存可以進行配置和更改,并且可以動態加載和卸載。 hibernate還為查詢結果提供了一個查詢緩存,它依賴于第二級緩存;
二、一級緩存和二級緩存的比較
(1)第一級緩存 第二級緩存 存放數據的形式相互關聯的持久化對象 對象的散裝數據 緩存的范圍事務范圍,每個事務都有單獨的第一級緩存進程范圍或集群范圍,緩存被同一個進程或集群范圍內的所有事務共享并發訪問策略由于每個事務都擁有單獨的第一級緩存,不會出現并發問題,無需提供并發訪問策略由于多個事務會同時訪問第二級緩存中相同數據,因此必須提供適當的并發訪問策略,來保證特定的事務隔離級別數據過期策略沒有提供數據過期策略。
(2)處于一級緩存中的對象永遠不會過期,除非應用程序顯式清空緩存或者清除特定的對象必須提供數據過期策略,如基于內存的緩存中的對象的最大數目,允許對象處于緩存中的最長時間,以及允許對象處于緩存中的最長空閑時間物理存儲介質內存內存和硬盤。
(3)對象的散裝數據首先存放在基于內存的緩存中,當內存中對象的數目達到數據過期策略中指定上限時,就會把其余的對象寫入基于硬盤的緩存中。
(4)緩存的軟件實現在hibernate的session的實現中包含了緩存的實現由第三方提供,hibernate僅提供了緩存適配器(cacheprovider)。用于把特定的緩存插件集成到hibernate中。
(5)啟用緩存的方式只要應用程序通過session接口來執行保存、更新、刪除、加載和查詢數據庫數據的操作,hibernate就會啟用第一級緩存,把數據庫中的數據以對象的形式拷貝到緩存中,對于批量更新和批量刪除操作,如果不希望啟用第一級緩存,可以繞過hibernate api,直接通過jdbc api來執行指操作。
(6)用戶可以在單個類或類的單個集合的粒度上配置第二級緩存。如果類的實例被經常讀但很少被修改,就可以考慮使用第二級緩存。
(7)只有為某個類或集合配置了第二級緩存,hibernate在運行時才會把它的實例加入到第二級緩存中。用戶管理緩存的方式第一級緩存的物理介質為內存,由于內存容量有限,必須通過恰當的檢索策略和檢索方式來限制加載對象的數目。session的 evit()方法可以顯式清空緩存中特定對象,但這種方法不值得推薦。第二級緩存的物理介質可以是內存和硬盤,因此第二級緩存可以存放大量的數據,數據過期策略的maxelementsinmemory屬性值可以控制內存中的對象數目。
(8)管理第二級緩存主要包括兩個方面:選擇需要使用第二級緩存的持久類,設置合適的并發訪問策略:選擇緩存適配器,設置合適的數據過期策略。
三、 一級緩存的管理
(1)當應用程序調用session的save()、update()、savaeorupdate()、get()或load(),以及調用查詢接口的 list()、iterate()或filter()方法時,如果在session緩存中還不存在相應的對象,hibernate就會把該對象加入到第一級緩存中。當清理緩存時,hibernate會根據緩存中對象的狀態變化來同步更新數據庫。 session為應用程序提供了兩個管理緩存的方法: evict(object obj):從緩存中清除參數指定的持久化對象。 clear():清空緩存中所有持久化對象。
(2)save、update、saveorupdate、load、list、iterate、lock會向一級緩存存放數據;
save 案例:
1
2
3
4
5
6
7
|
//添加一個學生 student student= new student(); student.setname( "小東" ); s.save(student); //放入一級緩存 //我馬上查詢 student stu2=(student) s.get(student. class , student.getid()); //select system.out.println( "你剛剛加入的學生名字是" +stu2.getname()); |
(3)什么操作會從一級緩存取數據:get、load、list
get / load 會首先從一級緩存中取,如沒有.再有不同的操作[get 會立即向數據庫發請求,而load 會返回一個代理對象,直到用戶真的去使用數據,才會向數據庫發請求;
1
2
3
4
5
6
|
//查詢45號學生 student stu=(student) s.get(student. class , 45 ); system.out.println( "|||||||||||||||||||" ); string hql= "from student where id=45" ; student stu2=(student) s.createquery(hql).uniqueresult(); system.out.println(stu2.getname()); |
從上面的案例,我們看出 query.list() query.uniueresut() 不會從一級緩取數據! 但是query.list 或者query.uniquerestu() 會向一級緩存放數據的.
注意:
① 一級緩存不需要配置,就可以使用,它本身沒有保護機制,所以我們程序員要考慮這個問題,我們可以同 evict 或者 clear來清除session緩存中對象. evict 是清除一個對象,clear是清除所有的sesion緩存對象
② session級緩存中對象的生命周期, 當session關閉后,就自動銷毀.
③ 我們自己用hashmap來模擬一個session緩存,加深對緩存的深入.
四、hibernate二級緩存的管理
1. hibernate二級緩存策略的一般過程如下:
1) 條件查詢的時候,總是發出一條select * from table_name where …. (選擇所有字段)這樣的sql語句查詢數據庫,一次獲得所有的數據對象。
2) 把獲得的所有數據對象根據id放入到第二級緩存中。
3) 當hibernate根據id訪問數據對象的時候,首先從session一級緩存中查;查不到,如果配置了二級緩存,那么從二級緩存中查;查不到,再查詢數據庫,把結果按照id放入到緩存。
4) 刪除、更新、增加數據的時候,同時更新緩存。hibernate二級緩存策略,是針對于id查詢的緩存策略,對于條件查詢則毫無作用。為此,hibernate提供了針對條件查詢的query cache。
5) 二級緩存的對象可能放在內存,也可能放在磁盤.
2. 什么樣的數據適合存放到第二級緩存中?
1) 很少被修改的數據
2) 不是很重要的數據,允許出現偶爾并發的數據
3) 不會被并發訪問的數據
4) 參考數據,指的是供應用參考的常量數據,它的實例數目有限,它的實例會被許多其他類的實例引用,實例極少或者從來不會被修改。
3. 不適合存放到第二級緩存的數據?
1) 經常被修改的數據
2) 財務數據,絕對不允許出現并發
3) 與其他應用共享的數據。
4. 常用的緩存插件 hibernater二級緩存是一個插件,下面是幾種常用的緩存插件:
◆ehcache:可作為進程范圍的緩存,存放數據的物理介質可以是內存或硬盤,對hibernate的查詢緩存提供了支持。
◆oscache:可作為進程范圍的緩存,存放數據的物理介質可以是內存或硬盤,提供了豐富的緩存數據過期策略,對hibernate的查詢緩存提供了支持。
◆swarmcache:可作為群集范圍內的緩存,但不支持hibernate的查詢緩存。
◆jbosscache:可作為群集范圍內的緩存,支持事務型并發訪問策略,對hibernate的查詢緩存提供了支持。
5. 配置hibernate二級緩存的主要步驟:
1) 選擇需要使用二級緩存的持久化類,設置它的命名緩存的并發訪問策略。這是最值得認真考慮的步驟。
2) 選擇合適的緩存插件,然后編輯該插件的配置文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<property name= "hbm2ddl.auto" >update</property> <!-- 啟動二級緩存 --> <property name= "cache.use_second_level_cache" > true </property> <!-- 指定使用哪種二級緩存 --> <property name= "cache.provider_class" >org.hibernate.cache.oscacheprovider</property> <mapping resource= "com/hsp/domain/department.hbm.xml" /> <mapping resource= "com/hsp/domain/student.hbm.xml" /> <!-- 指定哪個domain啟用二級緩存 特別說明二級緩存策略: 1 . read-only 2 . read-write 3 . nonstrict-read-write 4 . transcational --> < class -cache class = "com.hsp.domain.student" usage= "read-write" /> |
3)可以把oscache.properties文件放在 src目錄下,這樣你可以指定放入二級緩存的對象capacity 大小. 默認1000
6.使用二級緩存:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
// todo auto-generated method stub //通過獲取一個sesion,讓hibernate框架運行(config->加載hibernate.cfg.xml) session s= null ; transaction tx= null ; try { //我們使用基礎模板來講解. s=hibernateutil.opensession(); tx=s.begintransaction(); //查詢45號學生 student stu1=(student) s.get(student. class , 45 ); //45->一級緩存 system.out.println(stu1.getname()); tx.commit(); } catch (exception e) { e.printstacktrace(); if (tx!= null ){ tx.rollback(); } } finally { if (s!= null && s.isopen()){ s.close(); } } system.out.println( "*********************************" ); try { //我們使用基礎模板來講解. s=hibernateutil.opensession(); tx=s.begintransaction(); //查詢45號學生 student stu1=(student) s.get(student. class , 45 ); system.out.println(stu1.getname()); student stu3=(student) s.get(student. class , 46 ); system.out.println(stu3.getname()); tx.commit(); } catch (exception e) { e.printstacktrace(); if (tx!= null ){ tx.rollback(); } } finally { if (s!= null && s.isopen()){ s.close(); } } //完成一個統計,統計的信息在sessfactory //sessionfactory對象. statistics statistics= hibernateutil.getsessionfactory().getstatistics(); system.out.println(statistics); system.out.println( "放入" +statistics.getsecondlevelcacheputcount()); system.out.println( "命中" +statistics.getsecondlevelcachehitcount()); system.out.println( "錯過" +statistics.getsecondlevelcachemisscount()); |
在配置了二級緩存后,請大家要注意可以通過 statistics,查看你的配置命中率高不高
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對服務器之家的支持。如果你想了解更多相關內容請查看下面相關鏈接
原文鏈接:https://blog.csdn.net/xlgen157387/article/details/40071651