hibernate數(shù)據(jù)加載
均可以根據(jù)指定的實(shí)體類和id從數(shù)據(jù)庫中讀取記錄,并返回與之對(duì)應(yīng)的實(shí)體對(duì)象。
區(qū)別:
1.如果未能發(fā)現(xiàn)符合條件的記錄,get方法返回null,而load方法會(huì)拋出一個(gè)ObjectNotFoundException。
2.Load方法可返回實(shí)體的代理類實(shí)例,而get方法永遠(yuǎn)直接返回實(shí)體類。
3.load方法可以充分利用內(nèi)部緩存和二級(jí)緩存中的現(xiàn)有數(shù)據(jù),而get方法僅在內(nèi)部緩存中查找,如果沒有發(fā)現(xiàn)對(duì)應(yīng)的數(shù)據(jù),將越過二級(jí)緩存,直接調(diào)用SQL完成數(shù)據(jù)讀取。
數(shù)據(jù)加載的過程:
1.在一級(jí)緩存中,根據(jù)實(shí)體類型和id進(jìn)行查找,如果在第一級(jí)緩存中命中,且數(shù)據(jù)狀態(tài)合法,則直接返回。
2.Session會(huì)在當(dāng)前"NonExists"記錄中進(jìn)行查找,如果在"NonExists"記錄中存在同樣的條件,返回null。
3.對(duì)load方法而言,如果內(nèi)部緩存中沒法現(xiàn)有效數(shù)據(jù),查詢二級(jí)緩存,命中則返回。
4.如果緩存中無有效數(shù)據(jù),發(fā)起數(shù)據(jù)庫查詢操作(Select SQL),如果經(jīng)過查詢未發(fā)現(xiàn)對(duì)應(yīng)記錄,將此次查詢的信息在"NonExists"中加以記錄,返回null.
5.根據(jù)映射配置和Select SQL查詢得到的ResultSet,創(chuàng)建對(duì)應(yīng)的數(shù)據(jù)對(duì)象。
6.將對(duì)象納入一級(jí)緩存。
7.執(zhí)行Interceptor.onLoad方法(如果有對(duì)應(yīng)的Interceptor)
8.將數(shù)據(jù)納入二級(jí)緩存
9.如果數(shù)據(jù)對(duì)象實(shí)現(xiàn)了LifeCycle接口,則調(diào)用數(shù)據(jù)對(duì)象的onLoad方法。
10.返回?cái)?shù)據(jù)對(duì)象。
批量查詢:Session.find/iterate
查詢性能往往是系統(tǒng)性能表現(xiàn)的一個(gè)重要方面,查詢機(jī)制的優(yōu)劣很大程度上決定了系統(tǒng)的整體性能。這個(gè)領(lǐng)域往往也存在最大的性能調(diào)整空間。
hibernate2中Session.find()對(duì)應(yīng)于3中的session.createQuery().list();
hibernate2中Session.iterate()對(duì)應(yīng)于3中的session.createQuery().iterate();
find和iterate區(qū)別:
find方法通過一條Select SQL實(shí)現(xiàn)了查詢操作,而iterate方法要執(zhí)行多條Select SQL.
iterate第一次查詢獲取所有符合條件的記錄的id,然后再根據(jù)各個(gè)id從庫表中讀取對(duì)應(yīng)的記錄,這是一個(gè)典型的N+1次的查詢問題,如果符合條件記錄有10000條,就需要執(zhí)行10001條Select SQL,可想性能會(huì)如何的差。
那為什么要提供iterator方法,而不只是提供高效率的find方法?
原因1.與hibernate緩存機(jī)制密切相關(guān)
find方法實(shí)際上是無法利用緩存的,它對(duì)緩存只寫不讀。
find方法只執(zhí)行一次SQL查詢,它無法判斷緩存中什么樣的數(shù)據(jù)是符合條件的,也無法保證查詢結(jié)果的完整性。而iterate方法,會(huì)首先查詢所有符合條件記錄的id,然后根據(jù)id去緩存中找,如果緩存中有該id,就返回,沒有可以根據(jù)id再去數(shù)據(jù)庫查詢。
String hql = "from TUser where age > ?";
List userList = session.find(hql, new Integer(18), Hibernate.INTEGER);
Iterator it = session.iterate(hql, new Integer(18), Hibernate.INTEGER);
順序執(zhí)行,iterate方法只會(huì)執(zhí)行一次SQL查詢,就是查找id,然后根據(jù)id就可以從緩存中獲得數(shù)據(jù)。
String hql = "from TUser where age > ?";
List userList = session.find(hql, new Integer(18), Hibernate.INTEGER);
userList = session.find(hql, new Integer(18), Hibernate.INTEGER);
緩存是不起作用的。
如果目標(biāo)數(shù)據(jù)讀取相對(duì)較為頻繁,通過iterate這種機(jī)制,會(huì)減少性能損耗。
原因2.內(nèi)存使用上的考慮
find方法將一次獲得的所有記錄并將其讀入內(nèi)存。如果數(shù)據(jù)量太大,可能會(huì)觸發(fā)OutOfMemoryError,從而導(dǎo)致系統(tǒng)異常。解決方案之一就是結(jié)合iterate方法和evict方法逐條對(duì)記錄進(jìn)行處理,將內(nèi)存消化保持在一個(gè)可以接受的范圍之內(nèi)。如:
String hql = "from TUser where age > ?";
Iterator it = session.iterate(hql, new Integer(18), Hibernate.INTEGER);
while(it.hasNext()) {
TUser user = (TUser)it.next();
//將對(duì)象從一級(jí)緩存中刪除
session.evict(user);
//二級(jí)緩存可以設(shè)定最大緩存量,達(dá)到后自動(dòng)對(duì)較老數(shù)據(jù)進(jìn)行廢除,但也可以通過編
//碼移除,這樣有助于保持?jǐn)?shù)據(jù)有效性。
sessionFactory.evict(TUser.class, user.getID());
}
批量數(shù)據(jù)處理的緩存同步問題
1.hibernate 2:
session.delete("from TUser");
會(huì)先查詢出id,然后逐個(gè)id執(zhí)行 delete from T_User where id = ?;
這樣造成效率低下。
為什么不直接采用一條Delete SQL?是因?yàn)镺RM要自動(dòng)維持其內(nèi)部狀態(tài)屬性,必須知道用戶作了什么操作。必須先從數(shù)據(jù)庫中獲得待刪除對(duì)象,然后根據(jù)這些對(duì)象對(duì)內(nèi)部緩存和二級(jí)緩存的數(shù)據(jù)進(jìn)行整理,以保持內(nèi)存狀態(tài)與數(shù)據(jù)庫的一致性。
單執(zhí)行一條刪除語句,刪除了什么數(shù)據(jù),只有數(shù)據(jù)庫知道,ORM無法得知。下次用戶從緩存中讀出的數(shù)據(jù),很可能就是被刪除的數(shù)據(jù),從而導(dǎo)致邏輯錯(cuò)誤。當(dāng)然,如果ORM可以根據(jù)DELETE SQL對(duì)緩存中數(shù)據(jù)進(jìn)行處理,將緩存中符合條件的對(duì)象廢除,然后再執(zhí)行DELETE SQL
,但是這樣導(dǎo)致緩存的管理復(fù)雜性大大增加(實(shí)際相當(dāng)于實(shí)現(xiàn)了一個(gè)支持SQL的內(nèi)存數(shù)據(jù)庫),這對(duì)于輕量級(jí)的ORM實(shí)現(xiàn)而言太苛刻了。
2.hibernate 3
性能提高。
但無法解決緩存同步上的問題,無法保證緩存數(shù)據(jù)的一致有效性。
Tuser user = (TUser)session.load(TUser.class, new Integer(1));
//通過Bulk delete/update 刪除id=1的用戶記錄
Transaction tx = session.beginTransaction();
String hql = "delete TUser where id=1";
Query query = session.createQuery(hql);
query.executeUpdate();
tx.commit();
//再次嘗試加載
user = (TUser)session.load(TUser.class, new Integer(1));
可以看到第二次加載是成功的。
posted on 2006-08-05 01:19 topquan 閱讀(1827) 評(píng)論(0) 編輯 收藏 所屬分類: Hibernate