網頁

2018/6/14

Hibernate JPA Entity 生命週期 (JPA Entity Lifecycle)

在使用Hibernate JPA之前要先了解什麼是Entity生命週期是什麼,否則會像我在進行新修刪查(CRUD)的操作時一直碰到錯誤。(我是新手)

先直接參考Entity 生命週期這篇。

Entity實體是指用來映射資料表的物件,例如資料庫有個EMPLOYEE資料表,則應用程式與之對映的Employee類別的實例就是Entity。

儘管Entity和MVC的Model很類似,但用途不同,請參考Java Model與Entity的區別,所以Employee類別的package名稱你要命名為com.yourname.entity.Employee

總之這種ORM框架映射的Entity實例存在是否被persistence context管理的狀態,而此狀態決定了Entity屬性變動時是否對映設的資料產生影響。

Entity的生命週期有四種狀態:

  • New: Entity實例沒有持久化id(primary key),尚未被persistence context管理。
  • Managed: Entiy實例有持久化id,已被persistence context管理。
  • Detached: Entity實例有持久化id,脫離persistence context的管理。
  • Removed: Entiyt實例有持久化Id,仍被persistence context管理,但資料庫中的對映資料已被刪除。

一個剛創建(new)的Entity的狀態即為New。

Employee employee = new Employee();

New狀態的Entity可使用EntityManagermerge()persist()來將該Entity納入PersistenceContext的管理,

EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = emf.createEntityManager();
...
Employee employee1 = new Employee(); // 創建employee1 (New,未被管理)
employee1.setId(1); // employee1的key為1

Employee employee2 = new Employee(); // 創建employee2 (New,未被管理)
employee2.setId(2); // employee1的key為2

EntityTransaction tx = em.getTransaction();
try {
    tx.begin();

    em.persist(employee1); // 將employee1加入PersistenceContext (Managed)
    Employee managedEmployee2 = em.merge(employee2); //將employee2加入PersistenceContext (Managed),回傳的Employee才是被管理的Entity
    em.remove(managedEmployee2); // 將employee2刪除。注意只有被管理的Entity才能刪除,否則未被管理的Entity即使id相同,刪除時會出現 java.lang.IllegalArgumentException: Removing a detached instance 錯誤

    tx.commit();
} catch (Excepton e) {
    tx.rollback();
}

persist()是將一個新的Entity加入PersistenceContext的管理。也就是新增的意思。

merge()是將Entity與PersistenceContext中具有相同id的Entity合併,也就修改的意思。

remove()是將PersistenceContext管理的Entity從資料庫刪除。

EntityManager關閉後,則原本Managed狀態的Entity就會變成Detached狀態。

PersistenceContext負責管理Entity實例的集合,其連結物件與資料表的狀態

PersistenceContext管理的Entity為Managed狀態,此時對Entity實例的任何變動, PersistenceContext都會將之對映至資料庫的變動。不過每次在程式中一變動Entity就存取資料庫IO會有效能議題,因此實際上對Entity的變動不會馬上反應至資料庫中,而會等到EntityManager作了flush()之後,在這之前對Entity的變動會先收集起來,等flush()再一次進行資料庫的變更。



沒有留言:

張貼留言