EntityManager 範圍


每 個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;
    }
....

您可以想像指定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;
    }
....


嚴格說來,本頁標題名稱應該叫作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狀態。