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