應(yīng)用程序通過new語句創(chuàng)建一個JAVA對象時,JVM會為這個對象分配一塊內(nèi)存空間,只要這個對象被引用,它就一直存在內(nèi)存中。如果不被引用了,就結(jié)束生命周期,會在適當(dāng)時候被回收。 一、理解Session緩存 Session的save()方法持久化一個對象,這個對象將被加入到Session緩存中,以后即使不再引用這個對象,但是只要Session緩存沒有被清空,這個對象仍然會處于生命周期中。 緩存的作用: 1.減少訪問數(shù)據(jù)庫的頻率。 2.保證緩存中的對象與數(shù)據(jù)庫中的相關(guān)記錄保持同步。 3.保證不出現(xiàn)訪問對象圖的死循環(huán),以及由死循環(huán)引起的JVM堆棧溢出異常。清理緩存時,會順序執(zhí)行一些SQL語句,具體見書。 默認(rèn)情況,Session會在下面的時間清理緩存: 1.調(diào)用commit()方法時 2.調(diào)用find()或者iterate()時,如果緩存中持久化對象的屬性變化,則要先清理緩存。 3.調(diào)用flush()方法時。此方法與commit()不同之處:此方法清理后不會提交事務(wù)。 4.例外情況:如果對象用native生成OID,那么當(dāng)調(diào)用save()方法時,會立即執(zhí)行insert語句。 如果需要更改Session清理緩存的時間點,用Session的setFlushMode()方法,有三種模式:查詢 commit flush FlushMode.AUTO 清理 清理 清理 FlushMode.COMMIT 不清理 清理 清理 FlushMode.NEVER 不清理 不清理 清理 設(shè)置代碼為:session. setFlushMode(FlushMode.COMMIT); 在下面的情況,需要調(diào)用flush()方法: 1.使用觸發(fā)器 2.混用了Hibernate API和JDBC API 3.JDBC驅(qū)動程序不健壯,導(dǎo)致Hibernate在自動清理緩存模式下無法正常工作。 二、 在Hibernate應(yīng)用中Java對象的狀態(tài) 需要被持久化的Java對象,在其生命周期中有三種狀態(tài): 1.臨時狀態(tài):剛用new創(chuàng)建,沒被持久化,沒在Session緩存中。 2.持久化狀態(tài):被持久化,加入到Session緩存中。 3.游離狀態(tài):被持久化,沒在Session緩存中。 (A) 臨時對象 特征:不在Session緩存中。在數(shù)據(jù)庫中無相應(yīng)記錄。 如何獲得:剛用new創(chuàng)建了一個對象。用Session的delete()方法。 (B) 持久化對象 特征:在一個Session實例的緩存中。在數(shù)據(jù)庫中有相應(yīng)記錄。Session清理緩存時,會根據(jù)持久化對象的屬性變化,來同步更新數(shù)據(jù)庫。 如何獲得: 用Session的save()方法。 用Session的load()或get()方法。 用Session的find()方法。 用Session的update()、saveOrUpdate()、lock()方法。 允許級聯(lián)保存時,如果一個持久化對象關(guān)聯(lián)一個臨時對象,Session清理緩存時,會把臨時對象轉(zhuǎn)變?yōu)槌志没瘜ο蟆?/span> 注意:應(yīng)避免一個Java對象同時被多個Session實例關(guān)聯(lián)。 (C) 游離對象 特征:不在Session緩存中。如果沒有其他程序刪除其對應(yīng)的紀(jì)錄,那么數(shù)據(jù)庫中應(yīng)該有其紀(jì)錄。 獲得:用Session的close()方法。用Session的evict()方法,可以從緩存中刪除一個持久化對象。 三、Session的保存、更新、刪除、查詢方法 <1>Session的save()方法 完成操作: 1.把要保存的對象加入到緩存中,將其變?yōu)槌志没瘜ο蟆?/span> 2.選用映射文件指定的標(biāo)識符生成器為持久化對象分配唯一的OID。(注意,不能修改持久化對象的OID。) 3.執(zhí)行一個insert語句。(不是立即執(zhí)行,而是當(dāng)Session清理緩存時,才會執(zhí)行。) 注意:不能將持久化對象或游離對象傳給save()方法。 <2>Session的update()方法 完成操作: 1.把對象重新加入到Session緩存中,使它變?yōu)槌志没瘜ο蟆?/span> 2.計劃一個update語句,當(dāng)Session清理緩存時,才會執(zhí)行。 如果用update關(guān)聯(lián)了一個游離對象,即使這個對象沒有被修改,也會生成update語句。要避免這種情況,可以將映射文件中<class>元素的select-before-update=”true”(默認(rèn)false),這樣Session清理緩存時,會先執(zhí)行一個select語句,將原來的數(shù)據(jù)調(diào)出來對比是否一致,只有改變了才會執(zhí)行update。這一方法會導(dǎo)致多select語句,所以如果數(shù)據(jù)不會經(jīng)常變化的話,再這樣設(shè)置。 注意:不能關(guān)聯(lián)在Session緩存中存在同樣OID的游離對象。不能關(guān)聯(lián)在數(shù)據(jù)庫中沒有相應(yīng)記錄的游離對象。 <3>Session的saveOrUpdate()方法 包含save()和update()方法的功能。遇到臨時對象,就調(diào)用save;遇到游離對象,調(diào)用update();遇到持久化對象,直接返回。 如何判斷是臨時or游離對象? 滿足下面情況之一,就是臨時對象: 1.OID取值為null 2.具有version屬性,并取值為null 3.映射文件的<id>元素設(shè)置了unsaved-valued屬性,且OID取值與其屬性值相符。例如,unsaved-valued=”0”,那么OID為0時是臨時對象。 4. 映射文件的version元素設(shè)置了unsaved-valued屬性,且version取值與其屬性值相符。 5.自定義了Interceptor實現(xiàn)類,且其isUnsaved()方法返回Boolean.TRUE。 <4>Session的load()、get()方法 都根據(jù)OID從數(shù)據(jù)庫中加載一個持久化對象。區(qū)別:如果不存在于OID對應(yīng)的紀(jì)錄,load()拋出異常,get()返回null。 <5>Session的delete()方法 刪除數(shù)據(jù)庫中與Java對象對應(yīng)的記錄。 |
|