hibernate的各種保存方式的區別

一、預備知識:

對於hibernate,它的對象有三種狀態,transient、persistent、detached

 

transient:瞬態或者自由態

persistent:持久化狀態

detached:脫管狀態或者遊離態

脫管狀態的實例可以通過調用save()、persist()或者saveOrUpdate()方法進行持久化。

持久化實例可以通過調用 delete()變成脫管狀態。通過get()或load()方法得到的實例都是持久化狀態的。

脫管狀態的實例可以通過調用 update()、saveOrUpdate()、lock()或者replicate()進行持久化。

save()和persist()將會引發SQL的INSERT,delete()會引發SQLDELETE,

而update()或merge()會引發SQLUPDATE。對持久化(persistent)實例的修改在刷新提交的時候會被檢測到,

它也會引起SQLUPDATE。saveOrUpdate()或者replicate()會引發SQLINSERT或者UPDATE

 

二、save 和update區別

把這一對放在第一位的原因是因爲這一對是最常用的。

save的作用是把一個新的對象保存

update是把一個脫管狀態的對象保存

處於持久化的對象的任何變化,不必人工調用update語句,hibernate自己會執行update的sql語句。

換句話說,update動作僅僅對託管對象有用

save僅僅對瞬時對象有用

 

 

三,update 和saveOrUpdate區別
saveOrUpdate基本上就是合成了save和update
引用hibernate reference中的一段話來解釋他們的使用場合和區別
通常下面的場景會使用update()或saveOrUpdate():
程序在第一個session中加載對象
該對象被傳遞到表現層
對象發生了一些改動
該對象被返回到業務邏輯層
程序調用第二個session的update()方法持久這些改動

saveOrUpdate()做下面的事:
如果對象已經在本session中持久化了,不做任何事
如果另一個與本session關聯的對象擁有相同的持久化標識(identifier),拋出一個異常
如果對象沒有持久化標識(identifier)屬性,對其調用save()
如果對象的持久標識(identifier)表明其是一個新實例化的對象,對其調用save()
如果對象是附帶版本信息的(通過<version>或<timestamp>) 並且版本屬性的值表明其是一個新實例化的對象,save()它。
否則update() 這個對象

 

       四,persist和save區別

 

1,persist把一個瞬態的實例持久化,但是並"不保證"標識符被立刻填入到持久化實例中 ,標識符的填入可能被推遲到flush的時間。

2,persist"保證",當它在一個transaction外部被調用的時候並不觸發一個Sql Insert,這個功能是很有用的,

當我們通過繼承Session/persistence context來封裝一個長會話流程的時候,一個persist這樣的函數是需要的。

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

 

      五,merge和update區別

 

merger()方法,很神奇。它可以用來將一個託管(detached)的VO(Value Object)持久化到數據庫,以下是它持久化一個託管vo的步驟:
1.在持久化上下文(persist context)中查找與託管VO具有相同ID的PO(persist object),如果找到,就將託管的VO的值copy給PO,然後返回持久化以後的對象;
2.如果在持久化上下文中沒有找到,它就會到數據庫出找,而且是根據託管的VO提供的ID查找,然後就將託管的VO的值copy給PO,然後返回持久化以後的對象;
3.如果在數據庫也沒找到和託管的VO對應的記錄,它就會要求new一個和託管的VO相對應的持久化對象,然後執行拷貝,返回持久化以後的對象。
注意:如果傳給merge()方法的是一個遊離態的(transient)對象,那麼就會按照第三步執行。

根據對象得id判斷,如果是沒有保存狀態,就做新增;否則,就從數據庫裝載該對象。

 

merge 如果session中存在相同持久化標識(identifier)的實例,用用戶給出的對象的狀態覆蓋舊有的持久實例

如果session沒有相應的持久實例,則嘗試從數據庫中加載,或創建新的持久化實例,最後返回該持久實例

用戶給出的這個對象沒有被關聯到session上,它依舊是脫管的

重點是最後一句:

當我們使用update的時候,執行完成後,我們提供的對象A的狀態變成持久化狀態

但當我們使用merge的時候,執行完成,我們提供的對象A還是脫管狀態,hibernate或者new了一個B,或者檢索到

一個持久對象B,並把我們提供的對象A的所有的值拷貝到這個B,執行完成後B是持久狀態,而我們提供的A還是託管狀態

e.g.:update(object), 方法運行後, object是持久化狀態, 而Object obj = merge(object), 方法運行後, object是脫管狀態, obj是持久化狀態

 

六,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

 

 

 

persist和merge: 沒有立即和數據庫進行同步

save和update:    處理後的數據處於持久狀態,換句話說,調用sql進行和數據庫同步的步驟。

總的來說,對於長事務的處理,應該使用persist和merge。減少數據庫交互

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章