簡體   English   中英

EJB 3 中 EntityManager 的擴散

[英]Proliferation of EntityManager in EJB 3

考慮這種情況:


@Stateless
public class A{

        
    @PersistenceContext
    private EntityManager em;

    @EJB
    B b;

    @EJB
    C c;

    public void doSomeWork(){
    b.doSomeWork();
    c.doSomeWork();
    em.persist(someStuff);
    }
    
}
@Stateless
public class B{
        
    @PersistenceContext
    private EntityManager em;

    public void doSomeWork(){
    //Do stuff
    em.persist(stuff)
    }

    
}
@Stateless
public class C{
        
    @PersistenceContext
    private EntityManager em;

    public void doSomeWork(){
    //Do stuff
    em.persist(stuff)
    }

    
}

在這種情況下,我對同一事務使用三個不同的 EntityManagers(從class A的方法doSomeWork()開始

現在,同樣的事務,但只有一個 EntityManager:

@Stateless
public class A{

        
    @PersistenceContext
    private EntityManager em;

    @EJB
    B b;

    @EJB
    C c;

    public void doSomeWork(){
    b.setTheEntityManager(em);
    b.doSomeWork();
    c.setTheEntityManager(em);
    c.doSomeWork();
    em.persist(someStuff);
    }
    
}
@Stateless
public class B{
        
    private EntityManager em;

    public void setTheEntityManager(EntityManager em){
    this.em = em;
    }

    public void doSomeWork(){
    //Do stuff
    em.persist(stuff)
    }

    
}
@Stateless
public class C{
        
    private EntityManager em;

    public void setTheEntityManager(EntityManager em){
    this.em = em;
    }

    public void doSomeWork(){
    //Do stuff
    em.persist(stuff)
    }
}

我一直在閱讀有關 EntityManager 生命周期的信息,但我不知道在第二種情況下是否有任何優勢(在性能、數據庫連接等方面)。 我的第一個答案是肯定的,因為只有一個 EntityManager,但另一方面,我沒有看到任何使用這種方法的代碼示例(將 EntityManager 從 EJB 傳遞到 EJB)。 此外,Oracle 文檔說“通過自動傳播持久性上下文,應用程序組件不需要將 EntityManager 實例的引用傳遞給彼此以便在單個事務中進行更改。Java EE 容器管理容器管理的生命周期實體經理。”

您從容器中 @Inject 或 @Resource 的任何內容都不應傳遞到其他地方。 這是創建 memory 泄漏和/或未定義行為的可靠方法。 做第二個也沒有優勢,因為容器每次都會自動為您注入正確的 EntityManager :)

所以簡而言之,永遠不要做第二個場景,總是做第一個場景。 該容器實際上是注入一個代理,它將您路由到正確的(在您的情況下相同,因為您還沒有退出事務邊界)實體管理器。

發生的事情是對a.doSomeWork()的調用具有隱含的 TransactionAttribute.Required。 如果事務尚未啟動,容器會為您啟動一個。 對 B 和 C 的后續調用現在參與該事務。 當您退出a.doSomeWork()時,假設這是事務開始的地方,那就是事務提交的地方。 A、B 和 C 所做的任何事情都發生在同一個事務中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM