一、 一級緩存
1. 一級緩存隻緩存整個對象,不能緩存對象屬性;
2. 一級緩存是Session級的緩存,不能跨多個Session對象來使用;
3. Session的load/get方法支援一級緩存的讀和寫;
4. Query的list接口隻支援一級緩存的寫入,不能從一級緩存中讀出對象。list接口加載對象要發出SQL;
5. Query的iterate接口既支援一級緩存的寫入,也能從一級緩存中讀取對象(如果有的話)。每次用iterate接口查詢對象,都要先發SQL加載查詢對象的id清單。如果需要用到某個對象,則根據該對象的id從一級緩存中查詢,有則直接加載,沒有則發出SQL從資料庫加載(這時會出現1+N問題)。
6. Session的save方法會将save的對象放入一級緩存中,是以如果要save大批對象,則應該要及時清空一級緩存,可以采用Session的clear()方法。
7. 一級緩存是hibernate 預設使用的,無需配置即可使用。
二、 二級緩存
1. 二級緩存也是隻能緩存整個對象,不能緩存對象屬性,而且對load/get方法、list/iterate方法的在使用上跟一級緩存一樣。
2. 與一級緩存不同,二級緩存是SessionFactory級的緩存,它允許多個Session對象之間共用。
3. 使用二級緩存前必須進行一些準備步驟(以EhCache為例):
(1) 需要有EhCache的xml配置檔案(設定EhCache的“緩存對象最大數目”、“對象是否不失效”、“對象允許的空閑時間”、“對象的生存時間”及“對象數目超額時是否緩存至磁盤”);
(2) 在總配置檔案hibernate.cfg.xml中啟用二級緩存(預設開啟,無需顯示配置):
<property name="hibernate.cache.use_second_level_cache">true</property>
(3) 指定二級緩存的供應商:
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
(4) 指定需要緩存的類及緩存方式(可在hibernate.cfg.xml或對應的類的.hbm.xml中配置):
在hibernate.cfg.xml中配置:
<class-cache usage="read-only" class="my.Student"/>
在Student.hbm.xml中配置(必須在配置id前完成):
<cache usage="read-only"/>
(5) 可以通過Session動态設定是否允許對二級緩存進行讀和寫,方法是:session.setCacheMode(CacheMode.GET)和session.setCacheMode(CacheMode.PUT)
(6) SessionFactory的evit()會将一個對象逐處二級緩存。
三、 查詢緩存
查詢緩存是專為Query的list方法設計的。對于iterate()方法,無論是查詢對象屬性還是對象本身,查詢緩存用與不用都沒有差別!
1.用查詢緩存查詢屬性:
(1) 查詢緩存必須要在hibernate.cfg.xml中顯示啟用:
<property name="hibernate.cache.use_query_cache">true</property>
(2) 在代碼中如果要用到查詢緩存(無論是寫還是讀緩存),都要進行開啟操作,可通過Query的setCacheable(true)方法開啟;
(3) 查詢緩存的生命周期與Session無關(可以跨Session查詢),當查詢關聯的表發生改變,那麼查詢緩存的生命周期結束(delete、update、modify)
(4) 開啟查詢緩存,并用Query查詢對象的屬性(可以是一個或多個)時,采用Query的list方法可以把得到的屬性集合寫入查詢緩存中。如果查詢緩存已經有了該對象的屬性,那麼就不會發出SQL而直接從查詢緩存中取出來;
2.用查詢緩存查詢對象:
(5) 如果開啟查詢緩存并通過list接口查詢對象,在首次查詢時會發出SQL從資料庫中擷取對象,同時将對象的id清單放入查詢緩存中;如果再次用查詢緩存查詢對象,則會根據該對象的id發出SQL從資料庫中加載對象(這時會發出N條SQL語句)
(6) 如果同時開啟查詢和二級緩存,那麼(5)中就不會發出N條SQL語句了,而是直接從二級緩存中加載。(此時的list接口有了讀二級緩存的能力了!!!)