Hibernate性能優化
性能優化是一個很大的話題,大到程序架構優化,數據庫設計等,小到一個特定算法,甚至js優化等等。這里我們只簡單談一下hibernate的性能優化。
在使用Hibernate的時候,通過正確的方法和策略,可以提高執行效率。
(一)抓取策略
抓取策略(fetching strategy)是指:當應用程序需要在(Hibernate實體對象圖的)關聯關系間進行導航的時候, Hibernate如何獲取關聯對象的策略。抓取策略可以在O/R映射的元數據中聲明,也可以在特定的HQL 或條件查詢(Criteria Query)中重載聲明。
例如單端代理,集合代理,批量抓取等
設置方式通常為
*fetch="join",hibernate會通過一個select語句連接(內聯/外聯)抓取其關聯對象或集合
*fetch="subselect",另外發送一條select語句抓取在前面查詢到的所有實體的關聯集合
*可以使用fetch預抓取Classes,解決N+1問題,hql中使用“join fetch ” ,select s from Student s join fetch s.classes where s.id in(:ids)
*batch-size屬性,可以批量加載實體類
(二)緩存
緩存原則:通常讀遠遠大于寫的數據進行緩存
Hibernate的Session在事務級別進行持久化數據的緩存操作。 當然,也有可能分別為每個類(或集合),配置集群、或JVM級別(SessionFactory級別)的緩存。 你甚至可以為之插入一個集群的緩存。注意,緩存永遠不知道其他應用程序對持久化倉庫(數據庫)可能進行的修改 (即使可以將緩存數據設定為定期失效)。
1、一級緩存
一級緩存生命周期很短和session的生命周期一致,一級緩存也叫session級的緩存或事務級緩存
* load/get/iterate查詢實體對象時,支持一級緩存
* 一級緩存是緩存實體對像的,對屬性不緩存
*對于 大批量的數據添加
session.beginTransaction();
for (int i=0; i<100000; i++) {
Student student = new Student();
student.setName("張三" + i);
session.save(student);
//每20條更新一次
if (i % 20 == 0) {
session.flush();
//清除緩存的內容
session.clear();
}
}
session.getTransaction().commit();
2、二級緩存
二級緩存也稱為進程級的緩存或SessionFactory級的緩存,二級緩存可以被所有的session共享
二級緩存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二級緩存
二級緩存的配置和使用:
* 將ehcache.xml文件拷貝到src下
* 在hibernate.cfg.xml文件中加入緩存產品提供商
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
* 啟用二級緩存,這也是它的默認配置
<property name="hibernate.cache.use_second_level_cache">true</property>
* 指定哪些實體類使用二級緩存
可以在映射文件中采用<cache>標簽指定或在hibernate.cfg.xml文件中統一指定
如:
<!--
指定Student使用二級緩存
-->
<class-cache class="com.bjpowernode.hibernate.Student" usage="read-only"/>
注意使用緩存的策略,通常采用read-only和read-write
*二級緩存主要是緩存實體對象
*如果要清除二級緩存中的某些對象
//HibernateUtils.getSessionFactory().evict(Student.class);
HibernateUtils.getSessionFactory().evict(Student.class, 1);
*注意大批量數據更新時,如果配置了二級緩存建議禁用一級緩存和二級緩存的交互
session.beginTransaction();
//禁止一級緩存和二級緩存交互
session.setCacheMode(CacheMode.IGNORE);
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();
(三)查詢緩存
* 查詢緩存是緩存普通屬性結果集的
* 對實體對象的結果集會緩存id(在查詢緩存中,它并不緩存結果集中所包含的實體的確切狀態;它只緩存這些實體的標識符屬性的值、以及各值類型的結果。 )
查詢緩存的生命周期,當關聯的表發生修改,查詢緩存的生命周期結束
查詢緩存的配置和使用:
* 修改hibernate.cfg.xml文件,來開啟查詢緩存,默認是false是不起用的
<property name="hibernate.cache.use_query_cache">true</property>
* 必須在程序啟用
query.setCacheable(true)