Hibernate作為和數(shù)據(jù)庫數(shù)據(jù)打交道的框架,自然會(huì)設(shè)計(jì)到操作數(shù)據(jù)的效率問題,而對(duì)于一些頻繁操作的數(shù)據(jù),緩存策略就是提高其性能一種重要手段,而hibernate框架是支持緩存的,而且支持一級(jí)和二級(jí)兩種緩存,合理的使用緩存策略可以大大提高我們的操作數(shù)據(jù)效率,但是利用不能,可能會(huì)造成不必要的麻煩。
一,一級(jí)緩存(Session緩存):
Session緩存表示將查詢結(jié)果放置到Session的臨時(shí)存儲(chǔ)空間(一級(jí)緩存中)。Hibernate框架默認(rèn)支持一級(jí)緩存的。一級(jí)緩存的范圍較小,一旦Session關(guān)閉,那么緩存失效。我們使用框架的各種方法,例如:get,load,save,update,delete等都支持一級(jí)緩存的。
二,二級(jí)緩存(SessionFactory緩存):
1,概述:二級(jí)緩存其實(shí)就是將查詢的數(shù)據(jù)放置在SessionFactory臨時(shí)存儲(chǔ)空間中,因?yàn)橐粋€(gè)SessionFactory可以創(chuàng)建多個(gè)Session對(duì)象,所以范圍比Session緩存的要大,多個(gè)Session可以共享二級(jí)緩存的數(shù)據(jù)。當(dāng)然了二級(jí)緩存也不能存儲(chǔ)大量的數(shù)據(jù),這個(gè)要根據(jù)我們電腦配置進(jìn)行設(shè)置。
2,如何設(shè)置使用二級(jí)緩存呢?Hibernate默認(rèn)是不支持二級(jí)緩存的。
a,首先在hibernate.cfg.xml配置文件中添加屬性標(biāo)簽,啟用二級(jí)緩存:
<!--啟用二級(jí)緩存 -->
<propertyname="hibernate.cache.use_second_level_cache">true</property>
b,二級(jí)緩存需要使用額外的第三方組件:ehcache。需要我們拷入對(duì)應(yīng)的jar包,以及將對(duì)應(yīng)的ehcache.xml存放到src目錄下。在這個(gè)配置文件中,我們可以設(shè)置二級(jí)緩存的大小等。
c,讓框架識(shí)別添加入的ehcache緩存組件,在hibernate.cfg.xml配置文件中添加屬性標(biāo)簽:
<!--讓框架識(shí)別ehcache緩存組件 -->
<propertyname="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
d,設(shè)置需要緩存的映射類,這里只是將一些查詢操作比較頻繁的類指定即可,哪些不經(jīng)常操作的數(shù)據(jù),是沒有必要利用緩存的。這里例如:
<!-- 將指定的類存放到二級(jí)緩存中,其中read-only是指放入緩存的數(shù)據(jù)是只讀的-->
<class-cache usage="read-only" class="com.ljh.hibernate.pojo.Student"/>
3,緩存的操作數(shù)據(jù)原理:
查詢數(shù)據(jù)時(shí),會(huì)首先從一級(jí)緩存中取數(shù)據(jù),如果取上,則直接使用,否則到二級(jí)緩存中取,如果取到則直接使用,否則,就會(huì)發(fā)送語句查詢數(shù)據(jù)庫。這樣利用一級(jí)和二級(jí)緩存會(huì)提高訪問效率。
當(dāng)然使用二級(jí)緩存要慎重,要考慮數(shù)據(jù)的操作頻繁性,服務(wù)器的硬件配置,數(shù)據(jù)的安全性等等方面,這樣才能很好的利用二級(jí)緩存,提高我們操作數(shù)據(jù)的效率,否則使用不當(dāng)就會(huì)帶來不必要的麻煩。
三,Lazy(懶加載),因?yàn)楦杏XLazy也用到了緩存,可能放到這里不太合理吧。在前邊我們已經(jīng)設(shè)計(jì)到了lazy了,這里簡(jiǎn)單總結(jié)一下。
1,lazy(Hibernate的延遲加載功能):表示查詢當(dāng)前對(duì)象或關(guān)聯(lián)對(duì)象數(shù)據(jù)時(shí),不真正訪問數(shù)據(jù)庫,當(dāng)使用對(duì)象非主鍵屬性時(shí),才真正發(fā)送查詢語句,訪問數(shù)據(jù)庫。由于在某些情況下,查的數(shù)據(jù)在后續(xù)流程到可能用不上,如果做查詢處理就多余了,所以延遲加載功能可以提高性能,合理使用即可。當(dāng)然了Hibernate框架是通過Cglib代理來完成延遲加載功能的擴(kuò)展的。
2,用到lazy地方總結(jié),這里只是對(duì)類和映射的地方簡(jiǎn)單總結(jié)了一下,在實(shí)際運(yùn)用中我們還要學(xué)會(huì)恰當(dāng)?shù)倪x擇:
標(biāo)簽 | 起作用到什么地方 | 取值解釋 |
<class> | 針對(duì)load方法 | true : 延遲加載 (默認(rèn)) false : 禁用延遲加載 |
<set> | 針對(duì)于一對(duì)多,多對(duì)多 | true : 延遲加載 (默認(rèn)) false : 禁用延遲加載 extra : 支持延遲加載,在訪問集合自身信息時(shí)可以發(fā)送高效的查詢語句。(推薦) |
<many-to-one> | 針對(duì)于多對(duì)一,一對(duì)一 | false : 禁用延遲加載 proxy : 延遲加載 (默認(rèn)) no-proxy : 支持延遲加載,不使用cglbi代理的方式完成延遲加載。通過第三方的字節(jié)碼增強(qiáng)工具。 |
<one-to-one> | 針對(duì)一對(duì)一 | 和<many-to-one>標(biāo)簽一樣,這里需要注意: 一對(duì)一的主鍵關(guān)聯(lián)映射,根據(jù)主動(dòng)方(不含外鍵)查詢被動(dòng)方(既是主鍵,又是外鍵)時(shí)不支持延遲加載的。 |
3,遇到的問題:lazy,延遲加載功能是運(yùn)用的一級(jí)緩存,也就是利用的是session的內(nèi)存,一般情況下,我們?cè)谟猛?/span>session后會(huì)進(jìn)行關(guān)閉,但是關(guān)閉后我們就無法進(jìn)行延遲查詢數(shù)據(jù)了,也就是說,延遲加載功能就將失效,剖出異常:No Sesssion,所以這是需要我們解決的。
4.NoSession異常的解決:
a,解決原理:我們可以在dao層不進(jìn)行session的關(guān)閉,通過前邊學(xué)習(xí)的AOP編程思想,添加過濾器,在視圖層進(jìn)行數(shù)據(jù)取完畢后進(jìn)行關(guān)閉session,這樣就可以解決了NoSession異常了。但是怎么獲取呢?這里又想到了前邊學(xué)習(xí)的ThreadLocal,我們可以將Session對(duì)象放到Threadlocal對(duì)象中,和線程進(jìn)行綁定,到視圖層再通過ThreadLocal進(jìn)行獲取關(guān)閉即可。
b,解決方案,AOP編程思想,想必都想到了spring框架了吧,的確,Spring框架提供了OpenSessionInViewFilter過濾器解決NoSession異常,這里我們只需要配置一下即可。在web.xml中進(jìn)行此過濾器的配置即可:
這些是Hibernate框架中重要的知識(shí),我們可以通過合理使用緩存和lazy機(jī)制,使我們的程序變得性能更加強(qiáng),考慮優(yōu)化項(xiàng)目時(shí),這兩項(xiàng)是必須要考慮的。這些東西看起來是比較虛的內(nèi)容,還需要我們通過一些小例子和實(shí)際應(yīng)用加深理解。
聯(lián)系客服