1. 程式人生 > >【SSH網上商城專案實戰16】Hibernate的二級快取處理首頁的熱門顯示

【SSH網上商城專案實戰16】Hibernate的二級快取處理首頁的熱門顯示

 

  轉自:https://blog.csdn.net/eson_15/article/details/51405911

  網上商城首頁都有熱門商品,那麼這些商品的點選率是很高的,當用戶點選某個熱門商品後需要進入商品的詳細資訊頁面,就像淘寶裡面那樣。那麼每次點選都要去後臺查詢一下該商品的詳細資訊,就會發送相應的sql語句,每次重新整理一下詳細頁面也會發sql語句,這樣的話,效能肯定會受到很大的影響。那麼使用Hibernate的二級快取就可以解決這個問題。

        有些人可能會想,我們可以使用重定向,這樣的話,在使用者第一次訪問的時候把資訊查出來放到session中,以後每次使用者重新整理就可以去session中拿了,這樣就不用去資料庫中查詢了,這是有道理的,但是不能解決上面的問題,因為我們要解決的是多使用者去訪問同一商品,去點選同一商品,重定向只能保證同一使用者去點選或重新整理。但是二級快取可以解決這些問題。

        我們先詳細解說一下基於Hibernate4.3的二級快取技術,然後再針對本專案做一個具體的配置。

1. Hibernate4.3二級快取基本配置
        與Hibernate3不同,Hibernate4.3的核心包裡沒有跟快取相關的類,我們要用二級快取的話,需要加上快取的jar包,從官方下載的hibernate-release-4.3.11.Final中的lib/optional/ehcache中有二級快取所需要的jar包,先要新增到工程中。如下:

 然後我們在hibernate.cfg.xml中配置二級快取相關的配置:

複製程式碼
 1 <hibernate-configuration>
 2  
 3     <session-factory>
 4         <property name="dialect">
 5             org.hibernate.dialect.MySQLDialect
 6         </property>
 7         
 8         <property name="show_sql">true</property>
 9         
10         <!-- 配置二級快取提供商,注意此處並不是快取的jar包 -->
11         <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
12         
13         <mapping class="cn.it.shop.model.Category" />
14         <mapping class="cn.it.shop.model.Account" />
15         <mapping class="cn.it.shop.model.Product" />
16  
17         <!-- 配置哪些類支援快取,這裡主要是顯示首頁的熱門商品,所以Product類支援快取 -->
18         <class-cache usage="read-only" class="cn.it.shop.model.Product"/>
19     </session-factory>
20  
21 </hibernate-configuration>
複製程式碼

然後我們開啟tomcat伺服器,然後訪問首頁,點選熱門商品,後臺就沒有再發送sql語句了,大家可能會納悶,難道二級快取就這麼簡單?配置上面這兩個項就搞定了?其實到現在為止,二級快取已經生效的原因是它有個預設的配置,在上面那個ehcache-core-2.4.3.jar中有個ehcache-failsafe.xml檔案,裡面已經有了預設配置,我們等會再具體分析。我們先來分析一下Hibernate的查詢策略:

 

2. Hibernate4.3的查詢策略
        Hibernate支援兩種查詢方式:session查詢和hql查詢。
        session中有session.save()  update() delete() get() load()等方法,此方式僅僅操作一條記錄,預設不用任何配置就支援二級快取。因此:read-only配置對session是生效的。在session中如果二級快取中配置了read-only,則session.update()和delete()操作都會失敗,如果想要成功,則需要配置成read-write。但是save()和get() load()是成功的。
        hql:此方式預設是用來操作多條記錄,比如list()和executeUpdate() 方法。此方式預設二級快取的配置包括read-only是無效的。hql的list()查詢的是多條記錄,直接查詢資料庫,並將查詢的結果交給二級快取,便於get()和load()的呼叫。executeUpdate也是不支援二級快取的,也是直接到資料庫更新,Hibernate會保證資料庫與快取同步。注意:hql是沒有save()方法的,如果需要插入資料只能呼叫session.save()方法。
       【注】:Hibernate中的一級快取(預設存在)也稱為session級別快取,不是用來提升效能,而是用來處理事務的;二級快取為sessionFactory快取,對所有session都有效,生命週期與sessionFactory相同(sessionFactory是單例,而且專案啟動時候就會建立)。

        具體的查詢策略,我們看下面的這張圖:

【注】:圖片文字如果太小,可以把圖片拖到新的視窗看~

        以上就是Hibernate的查詢的策略,下面我們來繼續看二級快取的配置。

 

3. Hibernate4.3二級快取高階配置
        上面提到了,我們之所以在hibernate.cfg.xml中配置了兩項就可以使用二級快取,是因為有個預設的配置,下面我們先來看一下這個預設配置:

複製程式碼
 1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
 2     
 3     <!-- 如果快取記憶體溢位,則儲存到硬碟空間 -->
 4     <diskStore path="java.io.tmpdir"/>
 5  
 6     <defaultCache
 7         maxElementsInMemory="10000" : <!-- 記憶體支援的最大物件的數量 -->
 8         eternal="false"     :<!-- 物件是否永久生效,建議為false,這樣下面的兩個引數才會有效 -->
 9         timeToIdleSeconds="60" :<!-- 物件的間隔週期,預設單位為秒。即60秒後如果還沒人用這個物件,會提前銷燬 -->
10         timeToLiveSeconds="120" :<!-- 物件的生命週期,預設單位為秒 -->
11         overflowToDisk="true"    :<!-- 是否支援溢位到硬碟,建議為true -->
12          maxElementsOnDisk="10000000" :<!-- 硬碟上支援的最大物件的數量 -->
13         memoryStoreEvictionPolicy="LRU" :<!-- 物件的替換策略 -->
14        />     
15 </ehcache>
複製程式碼

 關於預設配置的相關解釋已經在上面的註釋中了,我們現在知道了,正因為這個預設的配置,才使得Hibernate4.3的二級快取得以正確執行。現在如果我們要自己進行快取的配置,就需要自己在src目錄下新建一個ehcache.xml檔案,然後在裡面對上面這些配置項重新配置即可。我們接下來要測試一下各個配置,在測試之前,我先把首頁顯示的情況貼出來,並編個號,等會測試的時候好說明:

以上是首頁顯示的部分內容,Hibernate已經從資料庫中幫我們查出了顯示資訊,並且已經顯示好了。我們將它們編個號,等會我們測試快取的時候就方便分析了。下面我們開始測試一下上面的快取配置項:

        測試一:測試記憶體中的物件數量。將配置改成下面情況:

1 <defaultCache
2          maxElementsInMemory="6" <!-- 設定只支援快取6個 -->
3          eternal="true"
4          overflowToDisk="false"
5          memoryStoreEvictionPolicy="FIFO" :<!-- 先進先出 -->
6          />

配置好後,我們重啟一下伺服器,開啟首頁,由於配置的是6個,所以快取中只存了最後查出來的6條記錄,也就是編號3-8,我們點選3-8中的任何一個商品進入商品詳細頁面,注意看後臺的控制檯沒有輸出任何查詢資訊,說明並沒有發sql語句,但是當我們點選編號2的商品時,後臺發了一條sql語句,即查詢了資料庫,我們後退再次點選2商品,就沒有再發sql語句了,說明已經放到快取裡了,但是快取只支援6條資料,因為配置的物件替換策略是先進先出,所以剛剛快取中的編號3被移除,我們點選一下3試試,發了一條sql語句,於是測試完畢,二級快取執行正常。

 

        測試二:測試物件的生命週期。將配置改成下面的情況:

複製程式碼
1 <defaultCache
2      maxElementsInMemory="100"
3      eternal="false" <!-- 配成false才能設定下面的生命週期 -->
4      timeToIdleSeconds="20" 
5      timeToLiveSeconds="40"
6      overflowToDisk="false"
7      memoryStoreEvictionPolicy="FIFO"
8      />
複製程式碼

上面配置了快取的時間為40秒,如果20秒沒有操作就移除。由於我們配了100條記錄,所以上面編號1-8都在快取裡,我們開啟伺服器後,隨便點選一個,比如點選編號8,沒有發出sql語句,正常,20秒後,再點選編號8,發了一條sql語句,說明我們配置的生命週期生效了。這裡要注意一下,不能配置太短,比如配置10秒,因為tomcat啟動也要好幾秒,如果配置少了,還沒測試可能時間已經到了……那就不行了。

 

        測試三: 測試二級快取是否支援硬碟儲存。

複製程式碼
1 <defaultCache
2      maxElementsInMemory="4"
3      eternal="false" <!-- 配成false才能設定下面的生命週期 -->
4      timeToIdleSeconds="100" 
5      timeToLiveSeconds="200"
6      overflowToDisk="true"  <!-- 配置成true才支援硬碟儲存 -->
7      memoryStoreEvictionPolicy="FIFO"
8      />
複製程式碼

我們將支援硬碟儲存設定成了true,並將二級快取最大儲存量配置成了4。重啟伺服器,因為二級快取最多存4條記錄,所以肯定是編號5-8,點選5-8肯定不會發sql語句,但是當我們點選1-4時,也不會發sql語句,因為我們設定了支援硬碟儲存,Hibernate將查詢結果存在硬碟上了,所以我們也可以直接拿到資料,不需要發sql語句。

 

        測試四: 測試二級快取的替換策略

 

複製程式碼
 1 <defaultCache
 2      <!-- 
 3       FIFO已經淘汰了,不會再用了…… 
 4       LRU:最近最少被訪問演算法(時間策略),會忽略訪問頻率,離現在最遠時間訪問的會被替換掉
 5       LFU:最近最未使用演算法(頻率測量),會忽略訪問的先後時間,訪問頻率最少的會被替換掉
 6      -->
 7      maxElementsInMemory="3"
 8      eternal="false" <!-- 配成false才能設定下面的生命週期 -->
 9      timeToIdleSeconds="100" 
10      timeToLiveSeconds="200"
11      overflowToDisk="false"  <!-- 配置成true才支援硬碟儲存 -->
12      memoryStoreEvictionPolicy="LFU"
13      />
複製程式碼

顧名思義,LRU和LFU分別是關注最後訪問時間和訪問頻率的,我們拿LFU來舉例子,現在我們設定了最大儲存為3條記錄,也就是編號6-8,現在我們依次訪問編號6三次,編號7兩次,編號8一次,都不會發sql語句,我們再訪問編號7,發了sql語句,現在編號7存在了快取裡,編號8已經被移除了,因為它訪問的次數最少,我們可以再次點選編號8測試一下,發出了sql語句,測試成功。如果是LRU,則剛剛移除的是編號6,因為編號6最早訪問的。

 

        到這裡,相信大家對二級快取的使用已經掌握了,二級快取的測試就到這裡。下面針對我們這個網上商城的專案做一下配置。

4. 網上商城專案的實際配置
        我們配置二級快取的最大記錄數為1000,設定生命週期為120秒,間隔週期為60秒,支援硬碟儲存,並且使用頻率優先(LFU)的替換策略,因為使用者點選率高的,肯定要放在二級快取裡。

複製程式碼
 1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
 2     
 3     <!-- 如果快取記憶體溢位,則儲存到硬碟空間 -->
 4     <diskStore path="java.io.tmpdir"/>
 5  
 6     <defaultCache
 7             maxElementsInMemory="1000"
 8             eternal="false"
 9             timeToIdleSeconds="60"
10             timeToLiveSeconds="120"
11             overflowToDisk="true"
12             memoryStoreEvictionPolicy="LFU"
13             />     
14 </ehcache>
複製程式碼

        好了,結合網上商城這個專案,Hibernate4.3的二級快取配置及使用就介紹完了。

  轉自:https://blog.csdn.net/eson_15/article/details/51405911

  網上商城首頁都有熱門商品,那麼這些商品的點選率是很高的,當用戶點選某個熱門商品後需要進入商品的詳細資訊頁面,就像淘寶裡面那樣。那麼每次點選都要去後臺查詢一下該商品的詳細資訊,就會發送相應的sql語句,每次重新整理一下詳細頁面也會發sql語句,這樣的話,效能肯定會受到很大的影響。那麼使用Hibernate的二級快取就可以解決這個問題。

        有些人可能會想,我們可以使用重定向,這樣的話,在使用者第一次訪問的時候把資訊查出來放到session中,以後每次使用者重新整理就可以去session中拿了,這樣就不用去資料庫中查詢了,這是有道理的,但是不能解決上面的問題,因為我們要解決的是多使用者去訪問同一商品,去點選同一商品,重定向只能保證同一使用者去點選或重新整理。但是二級快取可以解決這些問題。

        我們先詳細解說一下基於Hibernate4.3的二級快取技術,然後再針對本專案做一個具體的配置。

1. Hibernate4.3二級快取基本配置
        與Hibernate3不同,Hibernate4.3的核心包裡沒有跟快取相關的類,我們要用二級快取的話,需要加上快取的jar包,從官方下載的hibernate-release-4.3.11.Final中的lib/optional/ehcache中有二級快取所需要的jar包,先要新增到工程中。如下:

 然後我們在hibernate.cfg.xml中配置二級快取相關的配置:

複製程式碼
 1 <hibernate-configuration>
 2  
 3     <session-factory>
 4         <property name="dialect">
 5             org.hibernate.dialect.MySQLDialect
 6         </property>
 7         
 8         <property name="show_sql">true</property>
 9         
10         <!-- 配置二級快取提供商,注意此處並不是快取的jar包 -->
11         <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
12         
13         <mapping class="cn.it.shop.model.Category" />
14         <mapping class="cn.it.shop.model.Account" />
15         <mapping class="cn.it.shop.model.Product" />
16  
17         <!-- 配置哪些類支援快取,這裡主要是顯示首頁的熱門商品,所以Product類支援快取 -->
18         <class-cache usage="read-only" class="cn.it.shop.model.Product"/>
19     </session-factory>
20  
21 </hibernate-configuration>
複製程式碼

然後我們開啟tomcat伺服器,然後訪問首頁,點選熱門商品,後臺就沒有再發送sql語句了,大家可能會納悶,難道二級快取就這麼簡單?配置上面這兩個項就搞定了?其實到現在為止,二級快取已經生效的原因是它有個預設的配置,在上面那個ehcache-core-2.4.3.jar中有個ehcache-failsafe.xml檔案,裡面已經有了預設配置,我們等會再具體分析。我們先來分析一下Hibernate的查詢策略:

 

2. Hibernate4.3的查詢策略
        Hibernate支援兩種查詢方式:session查詢和hql查詢。
        session中有session.save()  update() delete() get() load()等方法,此方式僅僅操作一條記錄,預設不用任何配置就支援二級快取。因此:read-only配置對session是生效的。在session中如果二級快取中配置了read-only,則session.update()和delete()操作都會失敗,如果想要成功,則需要配置成read-write。但是save()和get() load()是成功的。
        hql:此方式預設是用來操作多條記錄,比如list()和executeUpdate() 方法。此方式預設二級快取的配置包括read-only是無效的。hql的list()查詢的是多條記錄,直接查詢資料庫,並將查詢的結果交給二級快取,便於get()和load()的呼叫。executeUpdate也是不支援二級快取的,也是直接到資料庫更新,Hibernate會保證資料庫與快取同步。注意:hql是沒有save()方法的,如果需要插入資料只能呼叫session.save()方法。
       【注】:Hibernate中的一級快取(預設存在)也稱為session級別快取,不是用來提升效能,而是用來處理事務的;二級快取為sessionFactory快取,對所有session都有效,生命週期與sessionFactory相同(sessionFactory是單例,而且專案啟動時候就會建立)。

        具體的查詢策略,我們看下面的這張圖:

【注】:圖片文字如果太小,可以把圖片拖到新的視窗看~

        以上就是Hibernate的查詢的策略,下面我們來繼續看二級快取的配置。

 

3. Hibernate4.3二級快取高階配置
        上面提到了,我們之所以在hibernate.cfg.xml中配置了兩項就可以使用二級快取,是因為有個預設的配置,下面我們先來看一下這個預設配置:

複製程式碼
 1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
 2     
 3     <!-- 如果快取記憶體溢位,則儲存到硬碟空間 -->
 4     <diskStore path="java.io.tmpdir"/>
 5  
 6     <defaultCache
 7         maxElementsInMemory="10000" : <!-- 記憶體支援的最大物件的數量 -->
 8         eternal="false"     :<!-- 物件是否永久生效,建議為false,這樣下面的兩個引數才會有效 -->
 9         timeToIdleSeconds="60" :<!-- 物件的間隔週期,預設單位為秒。即60秒後如果還沒人用這個物件,會提前銷燬 -->
10         timeToLiveSeconds="120" :<!-- 物件的生命週期,預設單位為秒 -->
11         overflowToDisk="true"    :<!-- 是否支援溢位到硬碟,建議為true -->
12          maxElementsOnDisk="10000000" :<!-- 硬碟上支援的最大物件的數量 -->
13         memoryStoreEvictionPolicy="LRU" :<!-- 物件的替換策略 -->
14        />     
15 </ehcache>
複製程式碼

 關於預設配置的相關解釋已經在上面的註釋中了,我們現在知道了,正因為這個預設的配置,才使得Hibernate4.3的二級快取得以正確執行。現在如果我們要自己進行快取的配置,就需要自己在src目錄下新建一個ehcache.xml檔案,然後在裡面對上面這些配置項重新配置即可。我們接下來要測試一下各個配置,在測試之前,我先把首頁顯示的情況貼出來,並編個號,等會測試的時候好說明:

以上是首頁顯示的部分內容,Hibernate已經從資料庫中幫我們查出了顯示資訊,並且已經顯示好了。我們將它們編個號,等會我們測試快取的時候就方便分析了。下面我們開始測試一下上面的快取配置項:

        測試一:測試記憶體中的物件數量。將配置改成下面情況:

1 <defaultCache
2          maxElementsInMemory="6" <!-- 設定只支援快取6個 -->
3          eternal="true"
4          overflowToDisk="false"
5          memoryStoreEvictionPolicy="FIFO" :<!-- 先進先出 -->
6          />

配置好後,我們重啟一下伺服器,開啟首頁,由於配置的是6個,所以快取中只存了最後查出來的6條記錄,也就是編號3-8,我們點選3-8中的任何一個商品進入商品詳細頁面,注意看後臺的控制檯沒有輸出任何查詢資訊,說明並沒有發sql語句,但是當我們點選編號2的商品時,後臺發了一條sql語句,即查詢了資料庫,我們後退再次點選2商品,就沒有再發sql語句了,說明已經放到快取裡了,但是快取只支援6條資料,因為配置的物件替換策略是先進先出,所以剛剛快取中的編號3被移除,我們點選一下3試試,發了一條sql語句,於是測試完畢,二級快取執行正常。

 

        測試二:測試物件的生命週期。將配置改成下面的情況:

複製程式碼
1 <defaultCache
2      maxElementsInMemory="100"
3      eternal="false" <!-- 配成false才能設定下面的生命週期 -->
4      timeToIdleSeconds="20" 
5      timeToLiveSeconds="40"
6      overflowToDisk="false"
7      memoryStoreEvictionPolicy="FIFO"
8      />
複製程式碼

上面配置了快取的時間為40秒,如果20秒沒有操作就移除。由於我們配了100條記錄,所以上面編號1-8都在快取裡,我們開啟伺服器後,隨便點選一個,比如點選編號8,沒有發出sql語句,正常,20秒後,再點選編號8,發了一條sql語句,說明我們配置的生命週期生效了。這裡要注意一下,不能配置太短,比如配置10秒,因為tomcat啟動也要好幾秒,如果配置少了,還沒測試可能時間已經到了……那就不行了。

 

        測試三: 測試二級快取是否支援硬碟儲存。

複製程式碼
1 <defaultCache
2      maxElementsInMemory="4"
3      eternal="false" <!-- 配成false才能設定下面的生命週期 -->
4      timeToIdleSeconds="100" 
5      timeToLiveSeconds="200"
6      overflowToDisk="true"  <!-- 配置成true才支援硬碟儲存 -->
7      memoryStoreEvictionPolicy="FIFO"
8      />
複製程式碼

我們將支援硬碟儲存設定成了true,並將二級快取最大儲存量配置成了4。重啟伺服器,因為二級快取最多存4條記錄,所以肯定是編號5-8,點選5-8肯定不會發sql語句,但是當我們點選1-4時,也不會發sql語句,因為我們設定了支援硬碟儲存,Hibernate將查詢結果存在硬碟上了,所以我們也可以直接拿到資料,不需要發sql語句。

 

        測試四: 測試二級快取的替換策略

 

複製程式碼
 1 <defaultCache
 2      <!-- 
 3       FIFO已經淘汰了,不會再用了…… 
 4       LRU:最近最少被訪問演算法(時間策略),會忽略訪問頻率,離現在最遠時間訪問的會被替換掉
 5       LFU:最近最未使用演算法(頻率測量),會忽略訪問的先後時間,訪問頻率最少的會被替換掉
 6      -->
 7      maxElementsInMemory="3"
 8      eternal="false" <!-- 配成false才能設定下面的生命週期 -->
 9      timeToIdleSeconds="100" 
10      timeToLiveSeconds="200"
11      overflowToDisk="false"  <!-- 配置成true才支援硬碟儲存 -->
12      memoryStoreEvictionPolicy="LFU"
13      />
複製程式碼

顧名思義,LRU和LFU分別是關注最後訪問時間和訪問頻率的,我們拿LFU來舉例子,現在我們設定了最大儲存為3條記錄,也就是編號6-8,現在我們依次訪問編號6三次,編號7兩次,編號8一次,都不會發sql語句,我們再訪問編號7,發了sql語句,現在編號7存在了快取裡,編號8已經被移除了,因為它訪問的次數最少,我們可以再次點選編號8測試一下,發出了sql語句,測試成功。如果是LRU,則剛剛移除的是編號6,因為編號6最早訪問的。

 

        到這裡,相信大家對二級快取的使用已經掌握了,二級快取的測試就到這裡。下面針對我們這個網上商城的專案做一下配置。

4. 網上商城專案的實際配置
        我們配置二級快取的最大記錄數為1000,設定生命週期為120秒,間隔週期為60秒,支援硬碟儲存,並且使用頻率優先(LFU)的替換策略,因為使用者點選率高的,肯定要放在二級快取裡。

複製程式碼
 1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
 2     
 3     <!-- 如果快取記憶體溢位,則儲存到硬碟空間 -->
 4     <diskStore path="java.io.tmpdir"/>
 5  
 6     <defaultCache
 7             maxElementsInMemory="1000"
 8             eternal="false"
 9             timeToIdleSeconds="60"
10             timeToLiveSeconds="120"
11             overflowToDisk="true"
12             memoryStoreEvictionPolicy="LFU"
13             />     
14 </ehcache>
複製程式碼

        好了,結合網上商城這個專案,Hibernate4.3的二級快取配置及使用就介紹完了。