Hibernate三種狀態(Transient、Persistent、Detached)各種儲存(save,persist,update,saveOrUpdte,merge,flush,lock)區別

來源:互聯網
上載者:User

一、三種狀態(Transient、Persistent、Detached)

在Hibernate中有三種狀態,對它的深入理解,才能更好的理解hibernate的運行機理,剛開始不太注意這些概念,後來發現它是重要的。對於理解hibernate,JVM和sql的關係有更好的理解。對於需要持久化的JAVA對象,在它的生命週期中有三種狀態,而且互相轉化。  1,  臨時狀態(Transient):用new建立的對象,它沒有持久化,沒有處於Session中,處於此狀態的對象叫臨時對象; 2,  持久化狀態(Persistent):已經持久化,加入到了Session緩衝中。如通過hibernate語句儲存的對象。處於此狀態的對象叫持久對象; 3,  游離狀態(Detached):持久化對象脫離了Session的對象。如Session緩衝被清空的對象。  特點:已經持久化,但不在Session緩衝中。處於此狀態的對象叫游離對象; ×√ 臨時狀態 (Transient) 持久化狀態 (Persistent) 游離狀態 (Detached) 是否處於Session緩衝中 × √ × 資料庫中是否有對應記錄 × √ √  游離對象和臨時對象異同: 兩者都不會被Session關聯,對象屬性和資料庫可能不一致; 游離對象有持久化對象關閉Session而轉化而來,在記憶體中還有對象所以此時就變成游離狀態了; 圖是精華:   二、各種儲存的區別(save,persist,update,saveOrUpdte,merge,flush,lock)  游離狀態的執行個體可以通過調用save()、persist()或者saveOrUpdate()方法進行持久化。  持久化執行個體可以通過調用 delete()變成脫管狀態。通過get()或load()方法得到的執行個體都是持久化狀態的。  脫管狀態的執行個體可以通過調用 update()、0saveOrUpdate()、lock()或者replicate()進行持久化。  save()和persist()將會引發SQL的INSERT,delete()會引發SQLDELETE,而update()或merge()會引發SQLUPDATE。對持久化(persistent)執行個體的修改在重新整理提交的時候會被檢測到,它也會引起SQLUPDATE。saveOrUpdate()或者replicate()會引發SQLINSERT或者UPDATE 2.1 save 和update區別  把這一對放在第一位的原因是因為這一對是最常用的。save的作用是把一個新的對象儲存update是把一個脫管狀態的對象儲存  2.2 update 和saveOrUpdate區別  這個是比較好理解的,顧名思義,saveOrUpdate基本上就是合成了save和update引用hibernate reference中的一段話來解釋他們的使用場合和區別通常下面的情境會使用update()或saveOrUpdate(): 程式在第一個session中載入對象 該對象被傳遞到表現層 對象發生了一些改動 該對象被返回到商務邏輯層 程式調用第二個session的update()方法持久這些改動  saveOrUpdate()做下面的事: 如果對象已經在本session中持久化了,不做任何事 如果另一個與本session關聯的對象擁有相同的持久化標識(identifier),拋出一個異常 如果對象沒有持久化標識(identifier)屬性,對其調用save() 如果對象的持久標識(identifier)表明其是一個新執行個體化的對象,對其調用save() 如果對象是附帶版本資訊的(通過<version>或<timestamp>) 並且版本屬性的值表明其是一個新執行個體化的對象,save()它。 否則update() 這個對象 2.3 persist和save區別  這個是最迷離的一對,表面上看起來使用哪個都行,在hibernate reference文檔中也沒有明確的區分他們.這裡給出一個明確的區分。(可以跟進src看一下,雖然實現步驟類似,但是還是有細微的差別)這裡參考http://opensource.atlassian.com/projects/hibernate/browse/HHH-1682中的一個說明:---------------------------------------------------------------------------------I found that a lot of people have the same doubt. To help to solve this issue I'm quoting Christian Bauer:"In case anybody finds this thread...  persist() is well defined. It makes a transient instance persistent. However, it doesn't guarantee that the identifier value will be assigned to the persistent instance immediately, the assignment might happen at flush time. The spec doesn't say that, which is the problem I have with persist(). persist() also guarantees that it will not execute an INSERT statement if it is called outside of transaction boundaries. This is useful in long-running conversations with an extended Session/persistence context.A method like persist() is required. save() does not guarantee the same, it returns an identifier, and if an INSERT has to be executed to get the identifier (e.g. "identity" generator, not "sequence"), this INSERT happens immediately, no matter if you are inside or outside of a transaction. This is not good in a long-running conversation with an extended Session/persistence context." ---------------------------------------------------------------------------------簡單翻譯一下上邊的句子的主要內容:1,persist把一個瞬態的執行個體持久化,但是並"不保證"標識符被立刻填入到持久化執行個體中,標識符的填入可能被延遲到flush的時間。 2,persist"保證",當它在一個transaction外部被調用的時候並不觸發一個Sql Insert,這個功能是很有用的,當我們通過繼承Session/persistence context來封裝一個長會話流程的時候,一個persist這樣的函數是需要的。 3,save"不保證"第2條,它要返回標識符,所以它會立即執行Sql insert,不管是不是在transaction內部還是外部 2.4 saveOrUpdateCopy,merge和update區別  首先說明merge是用來代替saveOrUpdateCopy的,這個詳細見文章最後(hibernate 3.2新的Session介面與之前介面的不同)然後比較update和mergeupdate的作用上邊說了,這裡說一下merge的如果session中存在相同持久化標識(identifier)的執行個體,用使用者給出的對象的狀態覆蓋舊有的持久執行個體 如果session沒有相應的持久執行個體,則嘗試從資料庫中載入,或建立新的持久化執行個體,最後返回該持久執行個體 使用者給出的這個對象沒有被關聯到session上,它依舊是脫管的 重點是最後一句:當我們使用update的時候,執行完成後,我們提供的對象A的狀態變成持久化狀態但當我們使用merge的時候,執行完成,我們提供的對象A還是脫管狀態,hibernate或者new了一個B,或者檢索到一個持久對象B,並把我們提供的對象A的所有的值拷貝到這個B,執行完成後B是持久狀態,而我們提供的A還是託管狀態  3.5 flush和update區別 這兩個的區別好理解update操作的是在脫管狀態的對象而flush是操作的在持久狀態的對象。預設情況下,一個持久狀態的對象是不需要update的,只要你更改了對象的值,等待hibernate flush就自動儲存到資料庫了。hibernate flush發生再幾種情況下:1,調用某些查詢的時候2,transaction commit的時候3,手動調用flush的時候  3.6 lock和update區別  update是把一個已經更改過的脫管狀態的對象變成持久狀態lock是把一個沒有更改過的脫管狀態的對象變成持久狀態對應更改一個記錄的內容,兩個的操作不同:update的操作步驟是:(1)更改脫管的對象->調用updatelock的操作步驟是:(2)調用lock把對象從脫管狀態變成持久狀態-->更改持久狀態的對象的內容-->等待flush或者手動flush  附:hibernate 3.2新的Session介面與之前介面的不同 hibernate 3中的session介面的不同hibernate3.2版本中session出現了2個新session介面:org.hibernate.Session老session介面:org.hibernate.classic.Session顧名思義,classic包下的session就是以前常用的session,新的這個相比老的有很大變化。下邊詳細列出1,去掉了所有的find方法在新的session介面中沒有find方法,而在老的session介面中把find全部注釋成deprecated了。2,去掉所有的saveOrUpdateCopy,使用merge代替,這是classic.Session注釋中的一段原話./**  * Copy the state of the given object onto the persistent object with the same  * identifier. If there is no persistent instance currently associated with  * the session, it will be loaded. Return the persistent instance. If the  * given instance is unsaved or does not exist in the database, save it and  * return it as a newly persistent instance. Otherwise, the given instance  * does not become associated with the session.  *  * @deprecated use {@link org.hibernate.Session#merge(String, Object)}  *  * @param object a transient instance with state to be copied  * @return an updated persistent instance  */注意這句:@deprecated use {@link org.hibernate.Session#merge(String, Object)}3,去掉了iterate方法給出的注釋是使用createQuery,自己獲得iterate4,去掉了filter方法@deprecated use {@link #createFilter(Object, String)}.{@link Query#list}給出的注釋說用createFilter代替,實際就是自己從createFilter獲得query然後自己查詢5,增加了一些方法具體自己看api吧,主要是提供了一些新的功能。總結:從上邊的改變不難看出hibernate對於介面的設定觀念改變了。 以前的策略是:盡量給出全的介面,這樣減少使用者的代碼量,所以filter直接返回collection,iterate直接返回iterate。但這樣的結果是過度的提供介面,造成了學習上的負擔和選擇上的負擔。如何記住這些函數,如何在眾多函數中選擇是個麻煩事情。凡是做java的都知道,用一個java的東西最辛苦的是選擇,在開源的世界裡邊選擇一個適合自己的工程,再在這個選擇的工程裡邊選擇實現方法因為可能提供很多種實現方法,而且有些還是deprecated的。 現在的策略:盡量簡化介面,或減少函數,或者簡化函數名,例如把saveOrUpdateCopy變成merge。這樣的好處是記憶學習負擔少。多寫幾句代碼不是特別麻煩。其實我個人來講更喜歡現在的感覺。以前的策略其實很大程度上是滿足程式員的個人需求,更有成就感。但確不適合使用者的需求。 ok,無論如何現在的情況是更好了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.