標籤:style blog color 使用 strong 檔案
hibernate緩衝包括一級緩衝,二級緩衝以及查詢快取
一級緩衝
一級緩衝是Session的緩衝,由於session對象的生命週期對應於一個事務,所有session的緩衝是事務範圍的緩衝。第一級緩衝是必須的,緩衝中的每個持久類對象都有唯一的OID。無需做任何配置,hibernate自動維護。
當執行load/get/list/iterator/ filter/save/update/saveOrUpdate等方法時會把得到的實體物件放入一級緩衝中(只支援實體物件緩衝,不支援屬性的緩衝),當在同一個session範圍內執行load/get/iterator等查詢語句查詢快取過的資料時(不包括list),Hibernate不會去資料庫中查詢。
1.load
在執行session.load時,Hibernate首先從當前session的一級緩衝中擷取id對應的值,在擷取不到的情況下,將根據該對象是否配置了二級緩衝來做相應的處理,如配置了二級緩衝,則從二級緩衝中擷取id對應的值,如仍然擷取不到則還需要根據是否配置了消極式載入來決定如何執行,如未配置消極式載入則從資料庫中直接擷取,在從資料庫擷取到資料的情況下,Hibernate會相應的填充一級緩衝和二級緩衝,如配置了消極式載入則直接返回一個代理類執行個體,只有在訪問執行個體時(get)才進行資料庫查詢的操作。
2.get
session.get與session.load的行為基本一致,只是當緩衝中沒有需要的對象時,session.get會直接從資料庫載入資料(session.load返回代理類執行個體)。
3.Query.list
list取到結果集後會填充一級、二級和查詢快取,但是list方法查詢資料時不會使用一級緩衝和二級緩衝的值,除非配置了查詢快取。
4.Query.iterator
在執行iterator時,先向資料庫發起的是select id from這樣的語句,擷取符合查詢條件的id,之後在進行iterator.next調用時才會根據id查看緩衝中是否存在資料,如果緩衝中沒有會發起session.load的調用擷取實際的資料。所有最理想狀態下iterator會發出一條查詢id的sql語句,但在最差的情況下會發出N+1條查詢語句。
一級緩衝管理常用api
evit(obj) : 將指定的持久化對象從一級緩衝中清除,釋放對象所佔用的記憶體資源,指定對象從持久化狀態變為脫管狀態,從而成為游離對象.
clear() : 將一級緩衝中的所有持久化對象清除,釋放其佔用的記憶體資源
contains(obj): 判斷指定的對象是否存在於一級緩衝中.
flush() :重新整理一級緩衝區的內容,使之與資料庫資料保持同步.
因為save方法支援緩衝,大批量資料添加時每save一個對象就往緩衝裡放,如果對象足夠多記憶體肯定要溢出。一般的做法是先判斷一下save了多少個對象,如果save了20個對象就手動清空緩衝。
1 for (int i=0; i<100; i++) { 2 Student student = new Student(); 3 student.setName("student" + i); 4 session.save(student); 5 //20條更新一次 6 if (i % 20 == 0) { 7 //清空緩衝前將緩衝中的資料與資料庫同步 8 session.flush(); 9 //清空緩衝10 session.clear();11 }12 }13
二級緩衝
二級緩衝需要sessionFactory來管理,它是進程級的緩衝,所有是session共用的,二級緩衝比較複雜,一般用第三方產品,官方推薦使用ehcache。
配置ehcache二級緩衝
1.添加jar包
1 <dependency>2 <groupId>org.hibernate</groupId>3 <artifactId>hibernate-ehcache</artifactId>4 <version>4.3.0.Final</version>5 </dependency>
2.Hibernate設定檔(hibernate4.0,不同版本hibernate下provider_class會有不同)
1 <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>2 <!-- 預設即為true -->3 <property name="hibernate.cache.use_second_level_cache">true</property>
3.ehcache設定檔ehcache.xm(根路徑下)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <ehcache> 3 <defaultCache 4 maxElementsInMemory="50000" 5 eternal="false" 6 overflowToDisk="true" 7 timeToIdleSeconds="3600" 8 timeToLiveSeconds="3600" 9 /> 10 11 <cache name="com.zlt.hibernatedemo.Student" 12 maxElementsInMemory="50000" 13 eternal="true" 14 />15 </ehcache>
4.類添加二級緩衝功能
方法一:配置hibernate.cfg.xml
<class-cache usage="read-only" class="com.zlt.hibernatedemo.Student"/>
方法二:配置hbm檔案
在<id>屬性前加入<cache usage="read-only"/>
二級緩衝緩衝的key為id,value為實體物件。一般load(),iterate()使用到二級緩衝,list()需要結合查詢快取使用,二級緩衝在資料發生任何變化(新增、更新、刪除)的情況下都會自動的被更新。
二級緩衝管理常用api
session.setCacheMode(CacheMode.IGNORE):禁止使用二級緩衝
evict(Class arg0, Serializable arg1): 將某個類的指定ID的持久化對象從二級緩衝中清除,釋放對象所佔用的資源.
例如sessionFactory.evict(Student.class, new Integer(1));
evict(Class arg0) 將指定類的所有持久化對象從二級緩衝中清除,釋放其佔用的記憶體資源.
例如sessionFactory.evict(Student.class);
evictCollection(Stringarg0) 將指定類的所有持久化對象的指定集合從二級緩衝中清除,釋放其佔用的記憶體資源.
例如sessionFactory.evictCollection("Grade.students");
查詢快取
查詢快取是專為Query的list方法設計的。對於iterate()方法,無論是查詢對象屬性還是對象本身,查詢快取用與不用都沒有區別
配置查詢快取
1.查詢快取必須要在hibernate.cfg.xml中顯示啟用:<property name="hibernate.cache.use_query_cache">true</property>
2.在代碼中如果要用到查詢快取(無論是寫還是讀緩衝),都要進行開啟操作,可通過Query的setCacheable(true)方法開啟;
查詢快取的生命週期與Session無關(可以跨Session查詢),當查詢關聯的表發生改變,那麼查詢快取的生命週期結束(delete、update、modify)
開啟查詢快取,並用Query查詢對象的屬性(可以是一個或多個)時,採用Query的list方法可以把得到的屬性集合寫入查詢快取中。如果查詢快取已經有了該對象的屬性,那麼就不會發出SQL而直接從查詢快取中取出來;
二級緩衝和查詢快取關係
1.關閉查詢快取,開啟二級緩衝時:
第二次查詢屬性時iterate只會發出擷取id列表的sql,list會發出和第一次一樣的請求實體的sql。
2.開啟查詢快取,關閉二級緩衝
如果開啟查詢快取並通過list介面查詢對象,在首次查詢時會發出SQL從資料庫中擷取對象,同時將對象的id列表放入查詢快取中;如果再次用查詢快取查詢對象,則會根據該對象的id(session.load)發出SQL從資料庫中載入對象(這時會發出N條SQL語句)
3.開啟查詢快取,開啟二級緩衝
第二次查詢屬性時iterate只會發出擷取id列表的sql,list不發sql(此時的list介面有了讀二級緩衝的能力)
以上說明iterate只和二級緩衝有關,list和二級緩衝和查詢快取都有關。