Session緩存其實就是一塊內存空間,在這個內存空間中存放了互相關聯的Java對象,Session負責根據持久化對象的狀態變化來同步更新數據庫.Session的緩存是內置的,不能被卸載,也被稱為Hibernate的第一級緩存,此外SessionFactory有一個內置的緩存和一個外置的緩存,其中外置的緩存是可插拔的緩存插件,也被稱為Hibernate的第二級緩存,在默認情況下,SessionFactory不會啟動這個緩存插件.
緩存的范圍和緩存的并發訪問策略
1.持久層的緩存范圍
事務范圍: 緩存只能被當前事務訪問,緩存的生命周期依賴于事務的生命周期.每個事務都有獨自的緩存
進程范圍: 緩存被進程內的所有事務共享,緩存的生命周期依賴于進程的生命周期. 因為進程的事務有可能并發訪問緩存,所以必須對緩存采取必要的事務隔離機制;
群集范圍: 在群集環境中, 緩存被同一個機器或多個機器上的多個進程共享. 緩存中的數據被復制到集群環境中的每個進程節點,進程之間通過遠程通信來保證緩存中數據的一致性,
緩存中的數據通常采用對象的散裝數據形式;
2.緩存并發訪問策略
由上可見, 進程范圍或群集范圍緩存,即第二級緩存,會出現并發問題.對第二級緩存可以設定以下四種類型的并發訪問策略,每一個策略對應一種事務隔離級別.
1) 事務型: 僅僅在受管理環境中適用,對于經常被讀但是很少被修改的數據,可以防止臟讀和不可重復讀的并發問題;
2)讀寫型: 僅僅在非群集的環境中適用,對于經常被讀但是很少被修改的數據,可以防止臟讀;
3)非嚴格讀寫型: 不保證緩存與數據庫中數據的一致性,對于極少被修改,并且允許偶爾臟讀的數據,可以采用這種策略;
4)只讀型: 對于從來不會被修改的數據,如參考數據,可以使用這個策略;
只有符合以下條件的數據才適合于存放到第二級緩存中:
1) 很少被修改的數據;
2) 不是很重要的數據,允許出現偶爾的并發問題;
3)不會被并發訪問的數據;
4)參考數據;
Hibernate的二級緩存SessionFactory是進程范圍或群集范圍的緩存,因此需要采用適當的并發訪問策略,提供事務隔離級別,而且可以在每個類或每個集合的粒度上配置第二級緩存.緩存適配器(Cache Provider)用于把具體的緩存實現軟件于Hibernate集成.Hibernate還為查詢結果提供了一個查詢緩存,它依賴于第二級緩存.
管理Hibernate的第一級緩存
Session為應用程序提供了兩個管理緩存方法evict(Object o)和clear()
evict(Object o) : 從緩存中清除參數指定的持久化對象;(適用于不希望session'按照該對象的狀態變化來同步更新數據庫和批量更新或批量刪除的場合)
clear(): 清空緩存中所有持久化對象
*對于更好的批量更新或者批量刪除的場合應該直接通過JDBC API訪問數據庫的過程, 執行SQL語句來減少Hibernate API的多次sql執行, 或者調用相關的存儲過程. 這個時候還得注意
Transaction接口來聲明事務邊界;
管理Hibernate的第二級緩存
由于第二級緩存是可配置的插件,Hibernate允許選用以下類型的緩存插件:
1) EHCache: 進程范圍內的緩存, 對Hibernate的查詢緩存提供了支持;(net.sf.hibernate.cache.EhCacheProvider EHCache插件的適配器)
2) OpenSymphony OSCache: 進程范圍內的緩存,提供了豐富的緩存數據過期策略,對Hibernate的查詢緩存提供了支持;(net.sf.hibernate.cache,OSCacheProvider OSCache插件
的適配器);
3) SwarmCache: 群集范圍的緩存,但不支持Hibernate的查詢緩存;(net.sf.hibernate.cache.SwarmCacheProvider SwarmCache插件的適配器)
4) JBossCache: 群集范圍內的緩存,支持事務并發訪問策略,對Hibernate的查詢緩存提供了支持;(net.sf.hibernate,cache.TreeCacheProvider JBossCache插件的適配器)
配置第二級緩存主要包含以下步驟:
1) 在各個映射文件中為持久化類設置第二級緩存后者在Hibernate的配置文件hibernate.cfg.xml中集中設置第二級緩存,設置它的命名緩存的并發訪問策略;
2)選擇合適的緩存插件,手工編輯配置文件,為每個命名緩存設置數據過期策略;
<class name="mypack.Category" table="CATEGORIES">
<cache usage="read-write"/>
<id name="id" type="long" column="ID">
...
</class>
*如果只在category中配置cache,當調用category.getItems().iterate()方法時,Hibernate只會把items集合中的元素存放到緩存中,此時Hibernate僅僅把與Category關聯的Item對象的OID存放
到緩存中.如果希望把整個Item對象散裝數據存入緩存,應該在Item.hbm.xml文件中設置cache元素
***************************************************************************************************************************************************
在默認情況下,Session會在下面的時間點清理緩存.
1) 當應用程序調用net.sf.hibernate.Transaction的commit()方法的時候,commit()方法先清理緩存, 然后再向數據庫提交事務;
2) 當應用程序調用Session的find()或者iterate()時, 如果緩存中持久化對象的屬性發生了變化, 就會先清理緩存, 以保證查詢結果能反映持久化對象的最新狀態;
3) 當應用程序顯式調用Session的flush()方法的時候;
1. Session的save()方法
save方法并不立即執行SQL insert語句, 只有當Session清理緩存的時, 才會執行SQL insert語句.如果在save()方法之后, 又修改了持久化對象的屬性, 這會使得Session在清理緩
存時, 額外執行SQL update語句.
2. Session的update()方法
update方法會生成或調用一個計劃的update語句,并且Session只有在清理緩存的時候才會執行update語句,在執行時才會把Customer對象當前的屬性值組裝到update語句中.
**通過update()方法使游離對象被一個Session關聯,即使沒有修改Customer對象的任何屬性,Session在清理緩存時也會執行由update()方法計劃的update語句. 如果希望Session僅僅當修
改了Customer對象的屬性時, 才執行update語句, 可以把映射文件中<class>元素的select-before-update設為true, 該屬性的默認值為false;
**當update()方法關聯一個游離對象時, 如果在Session的緩存中已經存在相同OID的持久化對象,會拋出異常.
3. Session的saveOrUpdate()方法
saveOrUpdate()方法同時包含了save()與update()方法的功能, 如果傳入的參數是臨時對象就調用save()方法; 如果傳入的參數是游離對象, 就調用update()方法; 如果傳入的參數
是持久化對象, 那就直接返回.
4. Session的load()和get()方法
Session的load()和get()方法都能根據給定的OID從數據庫中加載一個持久化對象, 這兩個方法的區別在于: 當數據庫中不存在與OID對應的記錄時, load()方法拋出
net.sf.hibernate.ObjectNotFoundException異常,而get()返回null.
5. Session的delete()方法
如果傳入的參數是持久化對象, Session就計劃執行一個delete語句. 如果傳入的參數是游離對象, 先使游離對象被Session關聯, 使它變為持久化對象, 然后計劃執行一個delete語
句. Session只有在清理緩存的時候才會執行delete語句.
該方法也能刪除多個對象, 但不推薦,效率低.如 session.delete("from Customer as c where c.id>8");
緩存的范圍和緩存的并發訪問策略
1.持久層的緩存范圍
事務范圍: 緩存只能被當前事務訪問,緩存的生命周期依賴于事務的生命周期.每個事務都有獨自的緩存
進程范圍: 緩存被進程內的所有事務共享,緩存的生命周期依賴于進程的生命周期. 因為進程的事務有可能并發訪問緩存,所以必須對緩存采取必要的事務隔離機制;
群集范圍: 在群集環境中, 緩存被同一個機器或多個機器上的多個進程共享. 緩存中的數據被復制到集群環境中的每個進程節點,進程之間通過遠程通信來保證緩存中數據的一致性,
緩存中的數據通常采用對象的散裝數據形式;
2.緩存并發訪問策略
由上可見, 進程范圍或群集范圍緩存,即第二級緩存,會出現并發問題.對第二級緩存可以設定以下四種類型的并發訪問策略,每一個策略對應一種事務隔離級別.
1) 事務型: 僅僅在受管理環境中適用,對于經常被讀但是很少被修改的數據,可以防止臟讀和不可重復讀的并發問題;
2)讀寫型: 僅僅在非群集的環境中適用,對于經常被讀但是很少被修改的數據,可以防止臟讀;
3)非嚴格讀寫型: 不保證緩存與數據庫中數據的一致性,對于極少被修改,并且允許偶爾臟讀的數據,可以采用這種策略;
4)只讀型: 對于從來不會被修改的數據,如參考數據,可以使用這個策略;
只有符合以下條件的數據才適合于存放到第二級緩存中:
1) 很少被修改的數據;
2) 不是很重要的數據,允許出現偶爾的并發問題;
3)不會被并發訪問的數據;
4)參考數據;
Hibernate的二級緩存SessionFactory是進程范圍或群集范圍的緩存,因此需要采用適當的并發訪問策略,提供事務隔離級別,而且可以在每個類或每個集合的粒度上配置第二級緩存.緩存適配器(Cache Provider)用于把具體的緩存實現軟件于Hibernate集成.Hibernate還為查詢結果提供了一個查詢緩存,它依賴于第二級緩存.
管理Hibernate的第一級緩存
Session為應用程序提供了兩個管理緩存方法evict(Object o)和clear()
evict(Object o) : 從緩存中清除參數指定的持久化對象;(適用于不希望session'按照該對象的狀態變化來同步更新數據庫和批量更新或批量刪除的場合)
clear(): 清空緩存中所有持久化對象
*對于更好的批量更新或者批量刪除的場合應該直接通過JDBC API訪問數據庫的過程, 執行SQL語句來減少Hibernate API的多次sql執行, 或者調用相關的存儲過程. 這個時候還得注意
Transaction接口來聲明事務邊界;
管理Hibernate的第二級緩存
由于第二級緩存是可配置的插件,Hibernate允許選用以下類型的緩存插件:
1) EHCache: 進程范圍內的緩存, 對Hibernate的查詢緩存提供了支持;(net.sf.hibernate.cache.EhCacheProvider EHCache插件的適配器)
2) OpenSymphony OSCache: 進程范圍內的緩存,提供了豐富的緩存數據過期策略,對Hibernate的查詢緩存提供了支持;(net.sf.hibernate.cache,OSCacheProvider OSCache插件
的適配器);
3) SwarmCache: 群集范圍的緩存,但不支持Hibernate的查詢緩存;(net.sf.hibernate.cache.SwarmCacheProvider SwarmCache插件的適配器)
4) JBossCache: 群集范圍內的緩存,支持事務并發訪問策略,對Hibernate的查詢緩存提供了支持;(net.sf.hibernate,cache.TreeCacheProvider JBossCache插件的適配器)
配置第二級緩存主要包含以下步驟:
1) 在各個映射文件中為持久化類設置第二級緩存后者在Hibernate的配置文件hibernate.cfg.xml中集中設置第二級緩存,設置它的命名緩存的并發訪問策略;
2)選擇合適的緩存插件,手工編輯配置文件,為每個命名緩存設置數據過期策略;
<class name="mypack.Category" table="CATEGORIES">
<cache usage="read-write"/>
<id name="id" type="long" column="ID">
...
</class>
*如果只在category中配置cache,當調用category.getItems().iterate()方法時,Hibernate只會把items集合中的元素存放到緩存中,此時Hibernate僅僅把與Category關聯的Item對象的OID存放
到緩存中.如果希望把整個Item對象散裝數據存入緩存,應該在Item.hbm.xml文件中設置cache元素
***************************************************************************************************************************************************
在默認情況下,Session會在下面的時間點清理緩存.
1) 當應用程序調用net.sf.hibernate.Transaction的commit()方法的時候,commit()方法先清理緩存, 然后再向數據庫提交事務;
2) 當應用程序調用Session的find()或者iterate()時, 如果緩存中持久化對象的屬性發生了變化, 就會先清理緩存, 以保證查詢結果能反映持久化對象的最新狀態;
3) 當應用程序顯式調用Session的flush()方法的時候;
1. Session的save()方法
save方法并不立即執行SQL insert語句, 只有當Session清理緩存的時, 才會執行SQL insert語句.如果在save()方法之后, 又修改了持久化對象的屬性, 這會使得Session在清理緩
存時, 額外執行SQL update語句.
2. Session的update()方法
update方法會生成或調用一個計劃的update語句,并且Session只有在清理緩存的時候才會執行update語句,在執行時才會把Customer對象當前的屬性值組裝到update語句中.
**通過update()方法使游離對象被一個Session關聯,即使沒有修改Customer對象的任何屬性,Session在清理緩存時也會執行由update()方法計劃的update語句. 如果希望Session僅僅當修
改了Customer對象的屬性時, 才執行update語句, 可以把映射文件中<class>元素的select-before-update設為true, 該屬性的默認值為false;
**當update()方法關聯一個游離對象時, 如果在Session的緩存中已經存在相同OID的持久化對象,會拋出異常.
3. Session的saveOrUpdate()方法
saveOrUpdate()方法同時包含了save()與update()方法的功能, 如果傳入的參數是臨時對象就調用save()方法; 如果傳入的參數是游離對象, 就調用update()方法; 如果傳入的參數
是持久化對象, 那就直接返回.
4. Session的load()和get()方法
Session的load()和get()方法都能根據給定的OID從數據庫中加載一個持久化對象, 這兩個方法的區別在于: 當數據庫中不存在與OID對應的記錄時, load()方法拋出
net.sf.hibernate.ObjectNotFoundException異常,而get()返回null.
5. Session的delete()方法
如果傳入的參數是持久化對象, Session就計劃執行一個delete語句. 如果傳入的參數是游離對象, 先使游離對象被Session關聯, 使它變為持久化對象, 然后計劃執行一個delete語
句. Session只有在清理緩存的時候才會執行delete語句.
該方法也能刪除多個對象, 但不推薦,效率低.如 session.delete("from Customer as c where c.id>8");