天天看點

Hibernate擷取資料方式與緩存使用

Hibernate擷取資料的方式有不同的幾種,其與緩存結合使用的效果也不盡相同,而Hibernate中具體怎麼使用緩存其實是我們很關心的一個問題,直接涉及到性能方面。

緩存在Hibernate中主要有三個方面:一級緩存、二級緩存和查詢緩存;一級緩存在Hibernate中對應的即為session範圍的緩存,也就是當 session關閉時緩存即被清除,一級緩存在Hibernate中是不可配置的部分;二級緩存在Hibernate中對應的即為 SessionFactory範圍的緩存,通常來講SessionFactory的生命周期和應用的生命周期相同,是以可以看成是程序緩存或叢集緩存,二級緩存在Hibernate中是可以配置的,可以通過class-cache配置類粒度級别的緩存(class-cache在class中資料發生任何變化的情況下自動更新),同時也可通過collection-cache配置集合粒度級别的緩存(collection-cache僅在 collection中增加了元素或者删除了元素的情況下才自動更新,也就是當collection中元素發生值的變化的情況下它是不會自動更新的),緩存自然會帶來并發的通路問題,這個時候相應的就要根據應用來設定緩存所采用的事務隔離級别,和資料庫的事務隔離級别概念基本一樣,沒什麼多介紹的, ^_^;查詢緩存在Hibernate同樣是可配置的,預設是關閉的,可以通過設定cache.use_ query_cache為true來打開查詢緩存。根據緩存的通常實作政策,我們可以來了解Hibernate的這三種緩存,緩存的實作通過是通過key/value的Map方式來實作,在 Hibernate的一級、二級和查詢緩存也同樣如此,一級、二級緩存使用的key均為po的主鍵ID,value即為po執行個體對象,查詢緩存使用的則為查詢的條件、查詢的參數、查詢的頁數,value有兩種情況,如果采用的是select po.property這樣的方式那麼value為整個結果集,如采用的是from這樣的方式那麼value為擷取的結果集中各po對象的主鍵ID,這樣的作用很明顯,節省記憶體,^_^

簡單介紹完Hibernate的緩存後,再結合Hibernate的擷取資料方式來說明緩存的具體使用方式,在Hibernate中擷取資料常用的方式主要有四種:Session.load、Session.get、Query.list、Query.iterator。

1、Session.load

      在執行session.load時,Hibernate首先從目前session的一級緩存中擷取id對應的值,在擷取不到的情況下,将根據該對象是否配置了二級緩存來做相應的處理,如配置了二級緩存,則從二級緩存中擷取id對應的值,如仍然擷取不到則還需要根據是否配置了延遲加載來決定如何執行,如未配置延遲加載則從資料庫中直接擷取,在從資料庫擷取到資料的情況下,Hibernate會相應的填充一級緩存和二級緩存,如配置了延遲加載則直接傳回一個代理類,隻有在觸發代理類的調用時才進行資料庫查詢的操作。

      在這樣的情況下我們就可以看到,在session一直打開的情況下,要注意在适當的時候對一級緩存進行重新整理操作,通常是在該對象具有單向關聯維護的時候,在Hibernate中可以使用象session.clear、session.evict的方式來強制重新整理一級緩存。

      二級緩存則在資料發生任何變化(新增、更新、删除)的情況下都會自動的被更新。

2、Session.get

      在執行Session.get時,和Session.load不同的就是在當從緩存中擷取不到時,直接從資料庫中擷取id對應的值。

3、Query.list

      在執行Query.list時,Hibernate的做法是首先檢查是否配置了查詢緩存,如配置了則從查詢緩存中查找key為查詢語句+查詢參數+分頁條件的值,如擷取不到則從資料庫中進行擷取,從資料庫擷取到後Hibernate将會相應的填充一級、二級和查詢緩存,如擷取到的為直接的結果集,則直接傳回,如擷取到的為一堆id的值,則再根據id擷取相應的值(Session.load),最後形成結果集傳回,可以看到,在這樣的情況下,list也是有可能造成N次的查詢的。

      查詢緩存在資料發生任何變化的情況下都會被自動的清空。

4、Query.iterator

      在執行Query.iterator時,和Query.list的不同的在于從資料庫擷取的處理上,Query.iterator向資料庫發起的是 select id from這樣的語句,也就是它是先擷取符合查詢條件的id,之後在進行iterator.next調用時才再次發起session.load的調用擷取實際的資料。

      可見,在擁有二級緩存并且查詢參數多變的情況下,Query.iterator會比Query.list更為高效。

這四種擷取資料的方式都各有适用的場合,要根據實際情況做相應的決定,^_^,最好的方式無疑就是打開show_sql選項看看執行的情況來做分析,系統結構上隻用保證這種調整是容易實作的就好了,在cache這個方面的調整自然是非常的容易,隻需要調整配置檔案裡的設定,而查詢的方式則可對外部進行屏蔽,這樣要根據實際情況調整也非常容易。

推薦三篇關于Hibernate緩存機制介紹的文章:

http://gocom.primeton.com/blog/index.php?op=ViewArticle&articleId=467&blogId=37&src=jdon&srcforum=62

http://club.gamvan.com/club/clubPage.jsp?ccStyle=0&tID=10456&ccID=37

http://www.devx.com/dbzone/Article/29685/1954?pf=true

繼續閱讀