2011年3月3日 星期四

Hibernate 教學 - hibernate 的物件生命週期

Hibernate 的物件生命週期可分為三大類

  • Transition (暫態) : 
          簡單說即是透過 new 產生的實體,尚未在資料庫有相對應的資料
          故還沒有被 Hibernate 納管
  • Persistent (持久) : 
          持久狀態即是已經被 Hibernate 所納管,即已被 Session 所管理,在持久狀態下的物件
          任何的更動都會被寫回資料庫,而持久狀態下的物件可由暫態並經由 save() 等方法
          使得該物件受 Session 所管納而形成持久狀態的物件,或是透過游離狀態並經過
          update() 或 saveOrUpdate() 讓離線狀態的物件再次受到 Session 所管納
           最後可以透過 get() 或 load() 直接取得資料庫的資料以形成持久狀態
  • Detached (游離或離線)
          指位於持久狀態下的物件,當所管納的 Session 執行 close() 或是 clear() 時
          則該物件就不被 Session 所納管,而形成了一種遊離或稱離線的狀態
          而游離狀態通常會再資料庫後方對應到一筆資料,除非你把它刪除
          此也是 Detached 和 Transition 最大的差別

        


















以下以一段程式來示範物件的三種狀態的移轉過程

package org.test;
import java.util.Date;
import org.control.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.model.Account;
import junit.framework.TestCase;
public class test extends TestCase   //繼承 JUnit 的 TestCase
{
    public void testSave()   //所有方法都須以 test...  開頭
    {
        SessionFactory factory = HibernateUtil.getSessionFactory();
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
  
        Account account1 = new Account();  //Transition 狀態
        account1.setName("test1");
        account1.setPassword("123456");
        account1.setDate(new Date());
  
        session.save(account1);    //Persistent 狀態

        /*** 1 ***/

        tx.commit();
        session.close();    //Detached 狀態
        

        /*** 2 ***/
    }
}

執行完上述程式之後 在資料庫應該會有一筆對應資料,例如

402880982e79b9e7012e79b9e9170001 test1 123456 2010-09-08 20:19:10

接著先測試看看,在持久狀態下的物件如果更改了部份屬性時,資料會如何變化

例如在以上程式的注解處 /*** 1 ***/ 插入一段程式,注意目前 account1 的狀態為 Persistent

account1.setName("test2");

則執行完上述程式後(假設目前資料表尚無任何資料) 應該會有一筆資料

402880982e79bf63012e79bf64f60001 test2 123456 2010-09-08 20:21:09

而在 JUnit 的 Console 中應該會顯示以下兩行的 SQL 執行語句

Hibernate: insert into Account (name, password, date, id) values (?, ?, ?, ?)
Hibernate: update Account set name=?, password=?, date=? where id=?

很顯然的由於 account1 目前爲 Session 所納管,而所有被 Session 所納管的物件

皆是持久狀態,而在 Persistent 的所有物件如果發生更動或變化時,皆會被寫回資料庫

所以以上的程式在一開始時是 account1.setName("test1");

在經過 session.save(account1) 之後成為了 Persistent 物件
此時再執行 account1.setName("test2")

則會使得 Hibernate 去針對該物件執行更新的動作,最後讓該筆資料的 name 欄位由 test1 變成 test2
-----------------------------------------------------------------------------------------------------------------------------------
接著再來觀察於 Detached 狀態下的物件如何依附到 Session 的環境下並對資料庫中的資料產生更動

首先在以上程式的注解處 /*** 2 ***/ 插入些許程式,注意此時的 account1 為 Detached
account1.setName("test2");
session = factory.openSession();
tx = session.beginTransaction();
session.saveOrUpdate(account1);  //此時的 account1 物件會從 Detached 狀態轉成 Persistent 狀態
tx.commit();
session.close();  

在原始程式中 執行到 session.close(); 之後,account1 即變成了 Detached 狀態

即是 account1 已經脫離的 session 的控管

以上的片斷程式 先將 account1 物件的 name 屬性更改為 test2

並再開啟一個 Session 並執行 saveOrUpdate() 方法,讓 account1 物件由 Detached 轉為 Persistent

所以以上的程式片段可以解釋成 再度將 account1 物件依附於持久環境並執行 update

以更新原本此 Detached 物件在後方資料庫中的資料

執行完上述程式後再資料表中(假設資料表並無任何資料)應該也會出現一筆


402880982e79fd20012e79fd22510001 test2 123456 2010-09-08 20:40:35

沒有留言:

張貼留言