Hibernate性能優化策略(二)

緩存機制
緩存是介於應用程序和物理數據源之間,其作用是爲了降低應用程序對物理數據源訪問的頻次,從而提高了應用的運行性能。緩存內的數據是對物理數據源中數據的複製,應用程序在運行時從緩存讀寫數據,在特定的時刻或事件會同步緩存和物理數據源的數據。
Hibernate的緩存包括Session的緩存和SessionFactory的緩存,成爲第一級緩存和二級緩存,這兩級緩存都位於持久化層,存放的都是數據庫數據的拷貝。
一級緩存
一級緩存生命週期很短和session的生命週期一致,一級緩存也叫session級的緩存或事務級緩存,在同一個Session中,它緩存的是實體對象,支持一級緩存的方法有load/get/iterate和save(同一個Session中先save後load不會發sql),但一級緩存是不會緩存普通屬性的。
在一級緩存中進行大批量數據添加時,要注意緩存溢出的情況,每添加數條數據要及時清理緩存,示例代碼如下:
[java] view plaincopy
/**
* 大批量的數據添加
*/
public void testCache7() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
for (int i=0; i<100; i++) {
Student student = new Student();
student.setName("張三" + i);
session.save(student);
//每20條更新一次
if (i % 20 == 0) {
session.flush();
//清除緩存的內容
session.clear();
}
}
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
二級緩存
二級緩存也稱爲進程級的緩存或SessionFactory級的緩存,二級緩存可以被所有的session共享,二級緩存的生命週期和SessionFactory的生命週期一致,SessionFactory可以管理二級緩存,二級緩存一般使用第三方的緩存產品,Hibernate文檔推薦了幾種:Hashtable(Hibernate內部,只做測試用)、EHCache、OSCache、SwarmCache、JBossTreeCache。
以EHCache爲例,二級緩存的的配置和使用:
1. 將ehcache.xml文件拷貝到src下;
2. 在hibernate.cfg.xml文件中加入緩存產品提供商<propertyname="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>;
3. 啓用二級緩存,這也是它的默認配置<propertyname="hibernate.cache.use_second_level_cache">true</property>;
4. 指定哪些實體類使用二級緩存
可以在映射文件中採用<cache>標籤指定或在hibernate.cfg.xml文件中統一指定,注意使用的策略,通常採用read-only和read-write;
緩存原則:通常讀遠遠大於寫的數據進行緩存。
一級緩存和二級緩存的交互中,可以通過一級緩存中的方法session.setCacheMode(CacheMode.IGNORE)禁止數據放到二級緩存中。在講一級緩存大批量數據添加時,爲了防止緩存溢出要隨時清理一級緩存,但是如果配置了二級緩存,如果不禁止二級緩存,同樣會引發緩存溢出而出錯,因此需要禁止一級緩存和二級緩存的交互。
查詢緩存
查詢緩存是緩存普通屬性結果集,可以對實體對象的結果集緩存id,查詢緩存的生命週期,當關聯的表發生修改,查詢緩存的生命週期結束,查詢緩存和session的生命週期是無關的,可以跨Session。查詢緩存只對query.list()起作用,query.iterate()查詢普通屬性不會使用查詢緩存。
查詢緩存的配置和使用:
1. 修改hibernate.cfg.xml文件,來開啓查詢緩存,默認是false是不起用的<propertyname="hibernate.cache.use_query_cache">true</property>
2. 必須在程序啓用 query.setCacheable(true)
鎖機制
其實,把鎖寫進Hibernate優化裏是有些問題的,本身加鎖是對性能極大的損耗,但鑑於有些時候我們不得不出於解決併發性問題而考慮加鎖時,就產生了性能優化方面的思考,在此我們可以選擇悲觀鎖和樂觀鎖,二者對性能的影響是不同的,因此合理選鎖也會提升Hibernate的性能。
悲觀鎖
悲觀鎖,通常是由數據庫機制實現的,在整個過程中把數據鎖住(查詢時),只要事務不釋放(提交/回滾),那麼任何用戶都不能查看或修改。
只需在load方法中加入第三個參數LockMode.UPGRADE即可。還有:
LockMode.NONE:無鎖機制。
LockMode.WRITE:Hibernate在Insert和Update記錄的時候會自動獲取。
LockMode.READ:Hibernate在讀取記錄的時候會自動獲取。
以上這三種鎖機制一般由Hibernate內部使用,如Hibernate爲了保證Update過程中對象不會被外界修改,會在save方法實現中自動爲目標對象加上WRITE鎖。
LockMode.UPGRADE:利用數據庫的forupdate子句加鎖。
LockMode.UPGRADE_NOWAIT:Oracle的特定實現,利用Oracle的for update nowait子句實現加鎖。
樂觀鎖
樂觀鎖,大多數的使用是採用數據版本的方式(version)實現,一般在數據庫中加入一個version字段,在讀取數據的時候將version讀取出來,在保存數據的時候判斷version的值是否小於數據庫中的version值,如果小於不予更新,否則給予更新。
Hibernate中在class標籤中通過屬性optimistic-lock=”version”來描述,optimistic-lock屬性可選取值:
none:無樂觀鎖。
version:通過版本機制實現樂觀鎖。
dirty:通過檢查發生變動過的屬性實現樂觀鎖。
all:通過檢查所有屬性實現樂觀鎖。
其中通過version實現的樂觀鎖機制是Hibernate官方推薦的樂觀鎖實現,同時也是Hibernate中,目前唯一在數據對象脫離Session發生修改的情況下依然有效
發佈了14 篇原創文章 · 獲贊 6 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章