SSH框架網(wǎng)上商城項(xiàng)目第16戰(zhàn)之Hibernate二級(jí)緩存處理首頁(yè)熱門顯示
網(wǎng)上商城首頁(yè)都有熱門商品,那么這些商品的點(diǎn)擊率是很高的,當(dāng)用戶點(diǎn)擊某個(gè)熱門商品后需要進(jìn)入商品的詳細(xì)信息頁(yè)面,就像淘寶里面那樣。那么每次點(diǎn)擊都要去后臺(tái)查詢一下該商品的詳細(xì)信息,就會(huì)發(fā)送相應(yīng)的sql語句,每次刷新一下詳細(xì)頁(yè)面也會(huì)發(fā)sql語句,這樣的話,性能肯定會(huì)受到很大的影響。那么使用Hibernate的二級(jí)緩存就可以解決這個(gè)問題。
有些人可能會(huì)想,我們可以使用重定向,這樣的話,在用戶第一次訪問的時(shí)候把信息查出來放到session中,以后每次用戶刷新就可以去session中拿了,這樣就不用去數(shù)據(jù)庫(kù)中查詢了,這是有道理的,但是不能解決上面的問題,因?yàn)槲覀円鉀Q的是多用戶去訪問同一商品,去點(diǎn)擊同一商品,重定向只能保證同一用戶去點(diǎn)擊或刷新。但是二級(jí)緩存可以解決這些問題。
我們先詳細(xì)解說一下基于Hibernate4.3的二級(jí)緩存技術(shù),然后再針對(duì)本項(xiàng)目做一個(gè)具體的配置。
1. Hibernate4.3二級(jí)緩存基本配置
與Hibernate3不同,Hibernate4.3的核心包里沒有跟緩存相關(guān)的類,我們要用二級(jí)緩存的話,需要加上緩存的jar包,從官方下載的hibernate-release-4.3.11.Final中的lib/optional/ehcache中有二級(jí)緩存所需要的jar包,先要添加到工程中。如下:

然后我們?cè)趆ibernate.cfg.xml中配置二級(jí)緩存相關(guān)的配置:
<hibernate-configuration> <session-factory> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <property name="show_sql">true</property> <!-- 配置二級(jí)緩存提供商,注意此處并不是緩存的jar包 --> <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <mapping class="cn.it.shop.model.Category" /> <mapping class="cn.it.shop.model.Account" /> <mapping class="cn.it.shop.model.Product" /> <!-- 配置哪些類支持緩存,這里主要是顯示首頁(yè)的熱門商品,所以Product類支持緩存 --> <class-cache usage="read-only" class="cn.it.shop.model.Product"/> </session-factory> </hibernate-configuration>
然后我們開啟tomcat服務(wù)器,然后訪問首頁(yè),點(diǎn)擊熱門商品,后臺(tái)就沒有再發(fā)送sql語句了,大家可能會(huì)納悶,難道二級(jí)緩存就這么簡(jiǎn)單?配置上面這兩個(gè)項(xiàng)就搞定了?其實(shí)到現(xiàn)在為止,二級(jí)緩存已經(jīng)生效的原因是它有個(gè)默認(rèn)的配置,在上面那個(gè)ehcache-core-2.4.3.jar中有個(gè)ehcache-failsafe.xml文件,里面已經(jīng)有了默認(rèn)配置,我們等會(huì)再具體分析。我們先來分析一下Hibernate的查詢策略:
2. Hibernate4.3的查詢策略
Hibernate支持兩種查詢方式:session查詢和hql查詢。
session中有session.save() update() delete() get() load()等方法,此方式僅僅操作一條記錄,默認(rèn)不用任何配置就支持二級(jí)緩存。因此:read-only配置對(duì)session是生效的。在session中如果二級(jí)緩存中配置了read-only,則session.update()和delete()操作都會(huì)失敗,如果想要成功,則需要配置成read-write。但是save()和get() load()是成功的。
hql:此方式默認(rèn)是用來操作多條記錄,比如list()和executeUpdate() 方法。此方式默認(rèn)二級(jí)緩存的配置包括read-only是無效的。hql的list()查詢的是多條記錄,直接查詢數(shù)據(jù)庫(kù),并將查詢的結(jié)果交給二級(jí)緩存,便于get()和load()的調(diào)用。executeUpdate也是不支持二級(jí)緩存的,也是直接到數(shù)據(jù)庫(kù)更新,Hibernate會(huì)保證數(shù)據(jù)庫(kù)與緩存同步。注意:hql是沒有save()方法的,如果需要插入數(shù)據(jù)只能調(diào)用session.save()方法。
【注】:Hibernate中的一級(jí)緩存(默認(rèn)存在)也稱為session級(jí)別緩存,不是用來提升性能,而是用來處理事務(wù)的;二級(jí)緩存為sessionFactory緩存,對(duì)所有session都有效,生命周期與sessionFactory相同(sessionFactory是單例,而且項(xiàng)目啟動(dòng)時(shí)候就會(huì)創(chuàng)建)。
具體的查詢策略,我們看下面的這張圖:

【注】:圖片文字如果太小,可以把圖片拖到新的窗口看~
以上就是Hibernate的查詢的策略,下面我們來繼續(xù)看二級(jí)緩存的配置。
3. Hibernate4.3二級(jí)緩存高級(jí)配置
上面提到了,我們之所以在hibernate.cfg.xml中配置了兩項(xiàng)就可以使用二級(jí)緩存,是因?yàn)橛袀€(gè)默認(rèn)的配置,下面我們先來看一下這個(gè)默認(rèn)配置:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- 如果緩存內(nèi)存溢出,則存儲(chǔ)到硬盤空間 --> <diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="10000" : <!-- 內(nèi)存支持的最大對(duì)象的數(shù)量 --> eternal="false" :<!-- 對(duì)象是否永久生效,建議為false,這樣下面的兩個(gè)參數(shù)才會(huì)有效 --> timeToIdleSeconds="60" :<!-- 對(duì)象的間隔周期,默認(rèn)單位為秒。即60秒后如果還沒人用這個(gè)對(duì)象,會(huì)提前銷毀 --> timeToLiveSeconds="120" :<!-- 對(duì)象的生命周期,默認(rèn)單位為秒 --> overflowToDisk="true" :<!-- 是否支持溢出到硬盤,建議為true --> maxElementsOnDisk="10000000" :<!-- 硬盤上支持的最大對(duì)象的數(shù)量 --> memoryStoreEvictionPolicy="LRU" :<!-- 對(duì)象的替換策略 --> /> </ehcache>
關(guān)于默認(rèn)配置的相關(guān)解釋已經(jīng)在上面的注釋中了,我們現(xiàn)在知道了,正因?yàn)檫@個(gè)默認(rèn)的配置,才使得Hibernate4.3的二級(jí)緩存得以正確執(zhí)行?,F(xiàn)在如果我們要自己進(jìn)行緩存的配置,就需要自己在src目錄下新建一個(gè)ehcache.xml文件,然后在里面對(duì)上面這些配置項(xiàng)重新配置即可。我們接下來要測(cè)試一下各個(gè)配置,在測(cè)試之前,我先把首頁(yè)顯示的情況貼出來,并編個(gè)號(hào),等會(huì)測(cè)試的時(shí)候好說明:

以上是首頁(yè)顯示的部分內(nèi)容,Hibernate已經(jīng)從數(shù)據(jù)庫(kù)中幫我們查出了顯示信息,并且已經(jīng)顯示好了。我們將它們編個(gè)號(hào),等會(huì)我們測(cè)試緩存的時(shí)候就方便分析了。下面我們開始測(cè)試一下上面的緩存配置項(xiàng):
測(cè)試一:測(cè)試內(nèi)存中的對(duì)象數(shù)量。將配置改成下面情況:
<defaultCache maxElementsInMemory="6" <!-- 設(shè)置只支持緩存6個(gè) --> eternal="true" overflowToDisk="false" memoryStoreEvictionPolicy="FIFO" :<!-- 先進(jìn)先出 --> />
配置好后,我們重啟一下服務(wù)器,打開首頁(yè),由于配置的是6個(gè),所以緩存中只存了最后查出來的6條記錄,也就是編號(hào)3-8,我們點(diǎn)擊3-8中的任何一個(gè)商品進(jìn)入商品詳細(xì)頁(yè)面,注意看后臺(tái)的控制臺(tái)沒有輸出任何查詢信息,說明并沒有發(fā)sql語句,但是當(dāng)我們點(diǎn)擊編號(hào)2的商品時(shí),后臺(tái)發(fā)了一條sql語句,即查詢了數(shù)據(jù)庫(kù),我們后退再次點(diǎn)擊2商品,就沒有再發(fā)sql語句了,說明已經(jīng)放到緩存里了,但是緩存只支持6條數(shù)據(jù),因?yàn)榕渲玫膶?duì)象替換策略是先進(jìn)先出,所以剛剛緩存中的編號(hào)3被移除,我們點(diǎn)擊一下3試試,發(fā)了一條sql語句,于是測(cè)試完畢,二級(jí)緩存執(zhí)行正常。
測(cè)試二:測(cè)試對(duì)象的生命周期。將配置改成下面的情況:
<defaultCache maxElementsInMemory="100" eternal="false" <!-- 配成false才能設(shè)置下面的生命周期 --> timeToIdleSeconds="20" timeToLiveSeconds="40" overflowToDisk="false" memoryStoreEvictionPolicy="FIFO" />
上面配置了緩存的時(shí)間為40秒,如果20秒沒有操作就移除。由于我們配了100條記錄,所以上面編號(hào)1-8都在緩存里,我們開啟服務(wù)器后,隨便點(diǎn)擊一個(gè),比如點(diǎn)擊編號(hào)8,沒有發(fā)出sql語句,正常,20秒后,再點(diǎn)擊編號(hào)8,發(fā)了一條sql語句,說明我們配置的生命周期生效了。這里要注意一下,不能配置太短,比如配置10秒,因?yàn)閠omcat啟動(dòng)也要好幾秒,如果配置少了,還沒測(cè)試可能時(shí)間已經(jīng)到了……那就不行了。
測(cè)試三:測(cè)試二級(jí)緩存是否支持硬盤存儲(chǔ)。
<defaultCache maxElementsInMemory="4" eternal="false" <!-- 配成false才能設(shè)置下面的生命周期 --> timeToIdleSeconds="100" timeToLiveSeconds="200" overflowToDisk="true" <!-- 配置成true才支持硬盤存儲(chǔ) --> memoryStoreEvictionPolicy="FIFO" />
我們將支持硬盤存儲(chǔ)設(shè)置成了true,并將二級(jí)緩存最大存儲(chǔ)量配置成了4。重啟服務(wù)器,因?yàn)槎?jí)緩存最多存4條記錄,所以肯定是編號(hào)5-8,點(diǎn)擊5-8肯定不會(huì)發(fā)sql語句,但是當(dāng)我們點(diǎn)擊1-4時(shí),也不會(huì)發(fā)sql語句,因?yàn)槲覀冊(cè)O(shè)置了支持硬盤存儲(chǔ),Hibernate將查詢結(jié)果存在硬盤上了,所以我們也可以直接拿到數(shù)據(jù),不需要發(fā)sql語句。
測(cè)試四:測(cè)試二級(jí)緩存的替換策略
<defaultCache <!-- FIFO已經(jīng)淘汰了,不會(huì)再用了…… LRU:最近最少被訪問算法(時(shí)間策略),會(huì)忽略訪問頻率,離現(xiàn)在最遠(yuǎn)時(shí)間訪問的會(huì)被替換掉 LFU:最近最未使用算法(頻率測(cè)量),會(huì)忽略訪問的先后時(shí)間,訪問頻率最少的會(huì)被替換掉 --> maxElementsInMemory="3" eternal="false" <!-- 配成false才能設(shè)置下面的生命周期 --> timeToIdleSeconds="100" timeToLiveSeconds="200" overflowToDisk="false" <!-- 配置成true才支持硬盤存儲(chǔ) --> memoryStoreEvictionPolicy="LFU" />
顧名思義,LRU和LFU分別是關(guān)注最后訪問時(shí)間和訪問頻率的,我們拿LFU來舉例子,現(xiàn)在我們?cè)O(shè)置了最大存儲(chǔ)為3條記錄,也就是編號(hào)6-8,現(xiàn)在我們依次訪問編號(hào)6三次,編號(hào)7兩次,編號(hào)8一次,都不會(huì)發(fā)sql語句,我們?cè)僭L問編號(hào)7,發(fā)了sql語句,現(xiàn)在編號(hào)7存在了緩存里,編號(hào)8已經(jīng)被移除了,因?yàn)樗L問的次數(shù)最少,我們可以再次點(diǎn)擊編號(hào)8測(cè)試一下,發(fā)出了sql語句,測(cè)試成功。如果是LRU,則剛剛移除的是編號(hào)6,因?yàn)榫幪?hào)6最早訪問的。
到這里,相信大家對(duì)二級(jí)緩存的使用已經(jīng)掌握了,二級(jí)緩存的測(cè)試就到這里。下面針對(duì)我們這個(gè)網(wǎng)上商城的項(xiàng)目做一下配置。
4. 網(wǎng)上商城項(xiàng)目的實(shí)際配置
我們配置二級(jí)緩存的最大記錄數(shù)為1000,設(shè)置生命周期為120秒,間隔周期為60秒,支持硬盤存儲(chǔ),并且使用頻率優(yōu)先(LFU)的替換策略,因?yàn)橛脩酎c(diǎn)擊率高的,肯定要放在二級(jí)緩存里。
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- 如果緩存內(nèi)存溢出,則存儲(chǔ)到硬盤空間 --> <diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="1000" eternal="false" timeToIdleSeconds="60" timeToLiveSeconds="120" overflowToDisk="true" memoryStoreEvictionPolicy="LFU" /> </ehcache>
好了,結(jié)合網(wǎng)上商城這個(gè)項(xiàng)目,Hibernate4.3的二級(jí)緩存配置及使用就介紹完了。
原文地址:http://blog.csdn.net/eson_15/article/details/51405911
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java Socket實(shí)現(xiàn)簡(jiǎn)單模擬HTTP服務(wù)器
這篇文章主要介紹了java Socket實(shí)現(xiàn)簡(jiǎn)單模擬HTTP服務(wù)器,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
idea兩側(cè)的maven-project-structure圖標(biāo)不見了如何解決
這篇文章主要介紹了如何解決idea兩側(cè)的maven-project-structure圖標(biāo)不見了問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
java非公平鎖知識(shí)點(diǎn)實(shí)例詳解
在本篇文章里小編給大家整理了一篇關(guān)于java非公平鎖知識(shí)點(diǎn)實(shí)例詳解,有興趣的朋友們可以學(xué)習(xí)參考下。2021-10-10
springboot springmvc拋出全局異常的解決方法
這篇文章主要為大家詳細(xì)介紹了springboot springmvc拋出全局異常的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
java批量采集豌豆莢網(wǎng)站Android應(yīng)用圖標(biāo)和包名
這篇文章主要介紹了java批量采集豌豆莢網(wǎng)站Android應(yīng)用圖標(biāo)和包名,主要用在做主題時(shí)替換這些常見應(yīng)用的圖片,需要的朋友可以參考下2014-06-06
Netty分布式ByteBuf使用的底層實(shí)現(xiàn)方式源碼解析
這篇文章主要為大家介紹了Netty分布式ByteBuf使用底層實(shí)現(xiàn)方式源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03

