hibernate中對象的3種狀態:瞬時態(Transient)、 持久態(Persistent)、脫管態(Detached)


  Hibernate的對象有3種狀態,分別為:瞬時態(Transient)、 持久態(Persistent)、脫管態(Detached)。

  處於持久態的對象也稱為PO(Persistence Object),瞬時對象和脫管對象也稱為VO(Value Object)。

  這3個狀態是hibernate里pojo對象的3個狀態,個人覺得這個對象始終都是pojo,而在這3個狀態中得vo和po只是它這時得一個表象而已(即它這時得狀態和po或vo狀態相同),並不能就說它此時是一個vo或po對象。而且po是根據具體orm框架生成得象JDO和hibernate生成它得機制就不一樣。這里說po只是廣義得描述一個狀態。

、瞬時狀態 (Transient)

  當我們通過Java的new關鍵字來生成一個實體對象時,這時這個實體對象就處於自由狀態,如下:
Customer customer = new Customer(“zx”,27,images);
  這時customer對象就處於自由狀態,為什么說customer對象處於自由狀態呢?這是因為,此時customer只是通過JVM獲得了一塊內存空間,還並沒有通過Session對象的save()方法保存進數據庫
  因此也就還沒有納入Hibernate的緩存管理中,也就是說customer對象現在還自由的游盪於Hibernate緩存管理之外。
  所以我們可以看出自由對象最大的特點就是,在數據庫中不存在一條與它對應的記錄。

  瞬時對象特點:

  (1) 不和 Session 實例關聯

  (2) 在數據庫中沒有和瞬時對象關聯的記錄

、持久狀態 (Persistent)

  持久化對象就是已經被保存進數據庫的實體對象,並且這個實體對象現在還處於Hibernate的緩存管理之中。這是對該實體對象的任何修改,都會在清理緩存時同步到數據庫中。如下所示:

Customer customer=new Customer(“zx”,27,images); tx=session.beginTransaction(); session.save(customer); customer=(Customer)session.load(Customer.class,”1”); customer.setAge(28); tx.commit();
  這時我們並沒有顯式調用session.update()方法來保存更新,但是對實體對象的修改還是會同步更新到數據庫中,因為此時customer對象通過save方法保存進數據庫后,已經是持久化對象了,然后通過load方法再次加載它,它仍然是持久化對象,所以它還處於Hibernate緩存的管理之中,這時當執行tx.commit()方法時,Hibernate會自動清理緩存,並且自動將持久化對象的屬性變化同步到到數據庫中。

  持久的實例在數據庫中有對應的記錄,並擁有一個持久化標識 (identifier)

  持久對象總是與 Session 和 Transaction 相關聯,在一個 Session 中,對持久對象的改變不會馬上對數據庫進行變更,而必須在 Transaction 終止,也就是執行 commit() 之后,才在數據庫中真正運行 SQL 進行變更,持久對象的狀態才會與數據庫進行同步。在同步之前的持久對象稱為臟 (dirty) 對象。

  瞬時對象轉為持久對象:

  (1) 通過 Session 的 save() 和 saveOrUpdate() 方法把一個瞬時對象與數據庫相關聯,這個瞬時對象就成為持久化對象。

  (2) 使用 fine(),get(),load() 和 iterater() 待方法查詢到的數據對象,將成為持久化對象。

  持久化對象的特點:

  (1) 和 Session 實例關聯

  (2) 在數據庫中有和持久對象關聯的記錄

、脫管狀態 (Detached)

  當一個持久化對象,脫離開Hibernate的緩存管理后,它就處於游離狀態,游離對象和自由對象的最大區別在於,游離對象在數據庫中可能還存在一條與它對應的記錄,只是現在這個游離對象脫離了Hibernate的緩存管理,而自由對象不會在數據庫中出現與它對應的數據記錄。如下所示:
Customer customer=new Customer(“zx”,27,images); tx=session.beginTransaction(); session.save(customer); customer=(Customer)session.load(Customer.class,”1”); customer.setAge(28); tx.commit(); session.close();
  當session關閉后,customer對象就不處於Hibernate的緩存管理之中了,但是此時在數據庫中還存在一條與customer對象對應的數據記錄,所以此時customer對象處於游離態

  與持久對象關聯的 Session 被關閉后,對象就變為脫管對象。對脫管對象的引用依然有效,對象可繼續被修改。

  脫管對象特點:

  (1) 本質上和瞬時對象相同

  (2) 只是比愛瞬時對象多了一個數據庫記錄標識值 id.

  持久對象轉為脫管對象:

  當執行 close() 或 clear(),evict() 之后,持久對象會變為脫管對象。

  瞬時對象轉為持久對象:

  通過 Session 的 update(),saveOrUpdate() 和 lock() 等方法,把脫管對象變為持久對象。

  三種狀態相互轉化的狀態圖如下:

4、結合 save(),update(),saveOrUpdate() 方法說明對象的狀態

(1)Save() 方法將瞬時對象保存到數據庫,對象的臨時狀態將變為持久化狀態。

  當對象在持久化狀態時,它一直位於 Session 的緩存中,對它的任何操作在事務提交時都將同步到數據庫,因此,對一個已經持久的對象調用 save()或 update() 方法是沒有意義的。如:

Student stu = new Strudnet(); stu.setCarId(“200234567”); stu.setId(“100”); // 打開 Session, 開啟事務 session.save(stu); stu.setCardId(“20076548”); session.save(stu); // 無效 session.update(stu); // 無效 // 提交事務,關閉 Session

(2)update() 方法兩種用途重新關聯脫管對象為持久化狀態對象,顯示調用 update() 以更新對象。調用 update() 只為了關聯一個脫管對象到持久狀態,當對象已經是持久狀態時,調用 update() 就沒有多大意義了。如:

// 打開 session ,開啟事務  stu = (Student)session.get(Student.class,”123456”); stu.setName(“Body”); session.update(stu); // 由於 stu 是持久對象,必然位於 Session 緩沖中, //對 stu 所做的變更將被同步到數據庫中。所以 update() 是沒有意義的,可以不要這句效果一樣的。 // 提交事務,關閉 Session

  Hibernate 總是執行 update 語句,不管這個脫管對象在離開 Session 之后有沒有更改過,在清理緩存時 Hibernate總是發送一條 update 語句,以確保脫管對象和數據庫記錄的數據一致,如:

Student stu = new Strudnet(); stu.setCarId(“1234”); // 打開 Session1, 開啟事務 session1.save(stu); // 提交事務,關閉 Session1 stu.set(“4567”); // 對脫管對象進行更改 // 打開 Session2, 開啟事務 session2.update(stu); // 提交事務,關閉 Session2

  注:即使把 session2.update(stu); 這句去掉,提交事務時仍然會執行一條 update() 語句。

  如果希望只有脫管對象改變了, Hibernate 才生成 update 語句,可以把映射文件中 <class> 標簽的 select-before-update 設為 true, 這種會先發送一條 select 語句取得數據庫中的值,判斷值是否相同,如果相同就不執行 update語句。不過這種做法有一定的缺點,每次 update 語句之前總是要發送一條多余的 select 語句,影響性能。對於偶爾更改的類,設置才是有效的,對於經常要更改的類這樣做是影響效率的。

(3)saveOrUpdate() 方法兼具 save() 和 update() 方法的功能,對於傳入的對象, saveOrUpdate() 首先判斷其是脫管對象還是臨時對象,然后調用合適的方法。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM