首頁 > Java > java教程 > 主體

Hibernate中物件的三種狀態及相互轉化

黄舟
發布: 2017-03-02 11:22:57
原創
1103 人瀏覽過

hibernate中的物件有三種狀態: 瞬時狀態 (Transient),持久狀態 (Persistent),脫管狀態(Detached)

 1.  瞬時狀態 (Transient)

當我們透過Java的new關鍵字來產生一個實體物件時,這時這個實體物件就處於自由狀態,如下:

 Customer customer=new Customer(“zx”,27,images);
登入後複製

這時customer物件就處於自由狀態,為什麼說customer物件處於自由狀態呢?這是因為,此時customer只是透過JVM獲得了一塊記憶體空間,還沒有透過Session物件的save()方法儲存進資料庫,因此也就還沒有納入Hibernate的快取管理中,也就是說customer物件現在還自由的遊蕩於Hibernate快取管理之外。所以我們可以看出自由物件最大的特點就是,在資料庫中不存在一條與它對應的記錄。

瞬時物件特性:

(1) 不和 Session 實例關聯

(2) 在資料庫中沒有和瞬時物件關聯的記錄

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) 在資料庫中有和持久性物件關聯的記錄

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 關閉後,物件就變成脫管物件。對脫管物件的引用依然有效,物件可繼續被修改。

脫管物件特性:

(1) 本質上和瞬時物件相同

(2) 只是比爱瞬时对象多了一个数据库记录标识值 id.

持久对象转为脱管对象:

当执行 close() 或 clear(),evict() 之后,持久对象会变为脱管对象。

瞬时对象转为持久对象:

通过 Session 的 update(),saveOrUpdate() 和 lock() 等方法,把脱管对象变为持久对象。

三种状态相互转化的状态图如下:

Hibernate中物件的三種狀態及相互轉化

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 语句,可以把映射文件中  标签的 select-before-update 设为 true, 这种会先发送一条 select 语句取得数据库中的值,判断值是否相同,如果相同就不执行 update语句。不过这种做法有一定的缺点,每次 update 语句之前总是要发送一条多余的 select 语句,影响性能。对于偶尔更改的类,设置才是有效的,对于经常要更改的类这样做是影响效率的。

(3)saveOrUpdate() 方法兼具 save() 和 update() 方法的功能,对于传入的对象, saveOrUpdate() 首先判断其是脱管对象还是临时对象,然后调用合适的方法。

 以上就是Hibernate中对象的三种状态及相互转化的内容,更多相关内容请关注PHP中文网(www.php.cn)!


來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!