Hibernate中的對象有三種狀態: 瞬時狀態(Transient),持久狀態(Persistent),
1. 脫管狀態(Detached)
1. 1.瞬時狀態(Transient)
由new命令開闢內存空間的Java對象,也就是平時所熟悉的普通Java對象。
如:Student stu = new Student();
瞬時對象特點:
(1)不和Session實例關聯
(2)在數據庫中沒有和瞬時對象關聯的記錄
2. 2.持久狀態(Persistent)
持久的實例在數據庫中有對應的記錄,並擁有一個持久化標識(identifier).
持久對象總是與Session和Transaction相關聯,在一個Session中,對持久對象的改變不會馬上對數據庫進行變更,而必須在Transaction終止,也就是執行commit()之後,纔在數據庫中真正運行SQL進行變更,持久對象的狀態纔會與數據庫進行同步。在同步之前的持久對象稱爲髒(dirty)對象。
瞬時對象轉爲持久對象:
(1) 通過Session的save()和saveOrUpdate()方法把一個瞬時對象與數據庫相關聯,這個瞬時對象就成爲持久化對象。
(2) 使用fine(),get(),load()和iterater()待方法查詢到的數據對象,將成爲持久化對象。
持久化對象的特點:
(1) 和Session實例關聯
(2) 在數據庫中有和持久對象關聯的記錄
3. 3.脫管狀態(Detached)
與持久對象關聯的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()首先判斷其是脫管對象還是臨時對象,然後調用合適的方法。