[英]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.