每 個EntityManager都與一個 Persistence Context 關聯,EntityManager不直接維護Entity,而是將之委托給Persistence Context,Persistence Context中會維護一組Entity實例,Entity實例在Persistence Context中為Managed狀態,這在 Entity 生命週期 中有說明。
之前有關於 使用 EntityManager 以及 Entity 生命週期,都是以Application-Managed EntityManager為例作說明,若是在Container-Managed EntityManager的情況下,您可以設定由容器來為您管理Persistence Context的範圍。
在 第一個 JPA(容器管理) 的例子中,在注入PersistenceContext至EntitySessionBean時,並沒有使用type指定 PersistenceContext的類型,則Persistence Context預設為Transaction-scoped,在EntitySessionBean方 法開始前會啟始交易,結束後停止交易,Persistence Context的存活範圍在交易之間,也就是Entity實例在交易完成之後,將會不受EntityManager的管理,將不在是Managed狀態,而處於Detached狀 態。
您可以在使用@PersistenceContext時,指定type屬性為PersistenceContextType.EXTENDED(預設為PersistenceContextType.TRANSACTION), 使Persistence Context為Extended Persistence Context,在EntityManager實例存活期間,Entity始終受到PersistenceContext的管理,Extended Persistence Context只能用於Stateful Session Bean中,Entity會一直受EntityManager的PersistenceContext管理,直到Stateful Session Bean結束而EntityManager關閉(close)為止。
舉個例子來說,當您使用預設的Transaction-scoped Persistence Context,則要更新資料表中的對應資料時,Detached狀態的Entity必須先使其回到Managed狀態,也就是您也許會在Session Bean中設計像以下的一些方法:
...
public User updateUser(User user) { // 若 user 已被變更
User user1 = entityManager.merge(user);
return user1;
}
public User updateUser(User user, String name) {
User user1 = entityManager.merge(user);
user1.setName(name);
return user1;
}
public User deleteUser(User user) {
User user1 = entityManager.merge(user);
entityManager.remove(user1);
return user1;
}
....
public User updateUser(User user) { // 若 user 已被變更
User user1 = entityManager.merge(user);
return user1;
}
public User updateUser(User user, String name) {
User user1 = entityManager.merge(user);
user1.setName(name);
return user1;
}
public User deleteUser(User user) {
User user1 = entityManager.merge(user);
entityManager.remove(user1);
return user1;
}
....
您可以想像指定type屬性為PersistenceContextType.EXTENDED 時,一旦進入EntityManager的管理,Entity一直處於Managed的狀態,若如此,則以上的程式片段中,有些不再需要:
...
public User updateUser(User user) { // 若 user 已被變更
User user1 = entityManager.merge(user);
return user1;
}
public User updateUser(User user, String name) {
User user1 = entityManager.merge(user);
user.setName(name);
return user;
}
public User deleteUser(User user) {
User user1 = entityManager.merge(user);
entityManager.remove(user);
return user;
}
....
public User updateUser(User user) { // 若 user 已被變更
User user1 = entityManager.merge(user);
return user1;
}
public User updateUser(User user, String name) {
User user1 = entityManager.merge(user);
user.setName(name);
return user;
}
public User deleteUser(User user) {
User user1 = entityManager.merge(user);
entityManager.remove(user);
return user;
}
....
嚴格說來,本頁標題名稱應該叫作PersistenceContext範圍,因為type屬性設定的正是EntityManager的Persistence Context有效範圍,不過一般也常稱為Transaction-scoped EntityManager或Extended-scoped EntityManager。
若為Application-Managed EntityManager,像是在 第一個 JPA(單機客戶端) 或 在 Servlet 中直接使用 JPA 中的Application-Managed EntityManager,則其行為類似於以上說明的Extended-scoped EntityManager,也就是Persistence Context是隨著EntityManager的關閉而失效,也就是當EntityManager關閉後,Entity就不再為Managed狀態。