1. 程式人生 > >【Web開發】Hibernate——持久化物件

【Web開發】Hibernate——持久化物件

所有內容均來自:輕量級JavaEE企業應用實戰(第五版)

1.Hiberante持久化類的要求

雖然Hibernate可以允許持久化類沒有標識屬性,但是這樣將導致Hibernate許多功能無法使用。且Hibernate建議使用可以為空的型別來作為標識屬性的型別,所以應儘量避免使用基本資料型別。
(1).為每個持久化類的成員提供setter and getter 方法。(Hibernate預設採用屬性方式來訪問持久化類的成員物件。)
(2).使用非final的類。(Hibernate預設在執行時使用Javassist生成代理,如果使用了final類,則無法生成Javaassist代理,從而無法進行效能優化。)
*(3).如果需要把持久化類的例項放在Set中,需重寫equals()和hashCode()方法。(使用業務鍵值相等來實現,需保證所選擇的一個或多個邏輯欄位的屬性值可以唯一的標識該例項)。

2.持久化物件的狀態說明

瞬態:物件由New建立,且雙衛與Hibernate Session關聯的物件。瞬態物件不會被持久化到資料庫中,特不會被賦予持久化標識。如果程式中失去了瞬態物件的引用,則會被垃圾回收機制銷燬。使用Hibernate Session可以將其變為持久化狀態。
持久化:持久化例項在資料庫中有對應的記錄,並擁有一個持久化標識。Hibernate會檢測處於持久化狀態物件的改動,並在當前操作執行完成時將物件資料寫回資料庫。開發者不需要手動進行update。
託管:某個例項曾處於持久化狀態下,但與之關聯的Session被關閉。託管物件的引用依然有效,如果重新讓託管物件與Session相連,則其將重新變為持久化狀態,託管期間進行的改動不會丟失,也可被寫入資料庫。用途:在託管狀態下,對該物件的操作無需鎖定資料庫,不會造成效能的下降。

3.改變持久化物件狀態的方法

遊離狀態的例項可以通過呼叫save()、persist()或者saveOrUpdate()方法進行持久化。
持久化例項可以通過呼叫 delete()變成脫管狀態。通過get()或load()方法得到的例項都是持久化狀態的。
脫管狀態的例項可以通過呼叫update()、updateOrSave()、lock()或merge()等進行持久化。

save()和persist()將會引發SQL的INSERT,delete()會引發SQL的DELETE,而update()或merge()會引發SQL的UPDATE。對持久化(persistent)例項的修改在重新整理提交的時候會被檢測到,它也會引起SQL的UPDATE。saveOrUpdate()或者replicate()會引發SQL INSERT或者UPDATE。

一,save 和update區別

把這一對放在第一位的原因是因為這一對是最常用的。
save的作用是把一個新的物件儲存
update是把一個脫管狀態的物件儲存

二,update 和saveOrUpdate區別

這個是比較好理解的,顧名思義,saveOrUpdate基本上就是合成了save和update
引用hibernate reference中的一段話來解釋他們的使用場合和區別
通常下面的場景會使用update()或saveOrUpdate():
程式在第一個session中載入物件
該物件被傳遞到表現層
物件發生了一些改動
該物件被返回到業務邏輯層
程式呼叫第二個session的update()方法持久這些改動

saveOrUpdate()做下面的事:
如果物件已經在本session中持久化了,不做任何事
如果另一個與本session關聯的物件擁有相同的持久化標識(identifier),丟擲一個異常
如果物件沒有持久化標識(identifier)屬性,對其呼叫save()
如果物件的持久標識(identifier)表明其是一個新例項化的物件,對其呼叫save()
如果物件是附帶版本資訊的(通過或) 並且版本屬性的值表明其是一個新例項化的物件,save()它。
否則update() 這個物件

三,persist和save區別

這個是最迷離的一對,表面上看起來使用哪個都行,在hibernate reference文件中也沒有明確的區分他們.
這裡給出一個明確的區分。
1,persist把一個瞬態的例項持久化,但是並”不保證”識別符號被立刻填入到持久化例項中,識別符號的填入可能被推遲
到flush的時間。

2,persist”保證”,當它在一個transaction外部被呼叫的時候並不觸發一個Sql Insert(直到flush),這個功能是很有用的,
當我們通過繼承Session/persistence context來封裝一個長會話流程的時候,一個persist這樣的函式是需要的。

3,save”不保證”第2條,它要返回識別符號,所以它會立即執行Sql insert,不管是不是在transaction內部還是外部

四,merge和update區別

update的作用上邊說了,這裡說一下merge的
如果session中存在相同持久化標識(identifier)的例項,用使用者給出的物件的狀態覆蓋舊有的持久例項
如果session沒有相應的持久例項,則嘗試從資料庫中載入,或建立新的持久化例項,最後返回該持久例項
使用者給出的這個物件沒有被關聯到session上,它依舊是脫管的
重點是最後一句:
當我們使用update的時候,執行完成後,我們提供的物件A的狀態變成持久化狀態
但當我們使用merge的時候,執行完成,我們提供的物件A還是脫管狀態,hibernate或者new了一個B,或者檢索到
一個持久物件B,並把我們提供的物件A的所有的值拷貝到這個B,執行完成後B是持久狀態,而我們提供的A還是託管狀態

五,flush和update區別

update操作的是在脫管狀態的物件
而flush是操作的在持久狀態的物件。
預設情況下,一個持久狀態的物件是不需要update的,只要你更改了物件的值,等待hibernate flush就自動
儲存到資料庫了。hibernate flush發生再幾種情況下:
1,呼叫某些查詢的時候
2,transaction commit的時候
3,手動呼叫flush的時候

六,lock和update區別

update是把一個已經更改過的脫管狀態的物件變成持久狀態
lock是把一個沒有更改過的脫管狀態的物件變成持久狀態
對應更改一個記錄的內容,兩個的操作不同:
update的操作步驟是:
(1)更改脫管的物件->呼叫update
lock的操作步驟是:
(2)呼叫lock把物件從脫管狀態變成持久狀態–>更改持久狀態的物件的內容–>等待flush或者手動flush