hibernate 三种状态的转换
一、遇到的神奇的事情
使用jpa操作數據庫,當我使用findAll()方法查處一個List的對象后,給對這個list的實體進行了一些操作,并沒有調用update 或者 saveOrUpdate方法,更改后的數據卻神奇的保存到數據庫里面去了。
最后簡單粗暴的解決辦法是把這份從數據里面查出來的List ?復制了一份,然后再操作,再返回。數據就正常了,數據庫也沒更新。后面找了資料才發現是jpa是對hibernate的封裝,底層是hibernate,這是hibernate的持久狀態搞的鬼。
二、hibernate 的三種狀態
1.?瞬時狀態?(Transient)?
當我們通過Java的new關鍵字來生成一個實體對象時,這時這個實體對象就處于自由狀態,如下: Customer customer=new Customer(“zx”,27,images); 這時customer對象就處于自由狀態,為什么說customer對象處于自由狀態呢?這是因為,此時customer只是通過JVM獲得了一塊內存空間,還并沒有通過Session對象的save()方法保存進數據庫,因此也就還沒有納入Hibernate的緩存管理中,也就是說customer對象現在還自由的游蕩于Hibernate緩存管理之外。所以我們可以看出自由對象最大的特點就是,在數據庫中不存在一條與它對應的記錄。瞬時對象特點:
- 不和?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)?對象。
瞬時對象轉為持久對象:
- 通過?Session?的?save()?和?saveOrUpdate()?方法把一個瞬時對象與數據庫相關聯,這個瞬時對象就成為持久化對象。
- 使用?fine(),get(),load()?和?iterater()?待方法查詢到的數據對象,將成為持久化對象。
持久化對象的特點:
- 和?Session?實例關聯
- 在數據庫中有和持久對象關聯的記錄
3.?脫管狀態?(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?被關閉后,對象就變為脫管對象。對脫管對象的引用依然有效,對象可繼續被修改。
脫管對象特點:
- 本質上和瞬時對象相同
- 只是比愛瞬時對象多了一個數據庫記錄標識值?id.
持久對象轉為脫管對象:
當執行?close()?或?clear(),evict()?之后,持久對象會變為脫管對象。
瞬時對象轉為持久對象:
通過?Session?的?update(),saveOrUpdate()?和?lock()?等方法,把脫管對象變為持久對象。
三、三種狀態的轉換
四、舉例子
1、結合?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()?首先判斷其是脫管對象還是臨時對象,然后調用合適的方法。
?
致謝:感謝您的耐心閱讀!總結
以上是生活随笔為你收集整理的hibernate 三种状态的转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端学习 -- Css -- 属性选择器
- 下一篇: 伊莱克斯冰箱质量如何