[英]CDI: Good way to produce correct EntityManager in an “Injection chain”
從使用PersistenceContext到使用@Injected DAO,我重寫了許多servlet。
在JSF中,我可以在@Produces方法中獲取對FacesContext的引用,並根據已登錄用戶返回正確的EM(或者如果已登錄,則使用默認值,表明有效用戶可用)。
當我必須為注入到不同servlet中的同一DAO生成不同的EM,並且要注入的EM取決於啟動“注入鏈”的Servlet時,如何以一種干凈的方式執行此操作?
預期結果:
Servlet 1 DaoA EntityM. x
+-----------+ +-----------+ +-----------+
| @Inject | Inject into| @Inject | Inject into| |
| DaoA daoA <-----+------+ E.M. em <------------+ |
| etc | | | //em x | | |
+-----------+ | +-----------+ +-----------+
| DaoB EntityM. x
| +-----------+ +-----------+
| | @Inject | Inject into| |
+------+ E.M. em <------------+ |
| //em x | | |
+-----------+ +-----------+
Servlet 2 DaoA EntityM. y
+-----------+ +-----------+ +-----------+
| @Inject | Inject into| @Inject | Inject into| |
| DaoA daoA <------------+ E.M. em <------------+ |
| | | //em y | | |
+-----------+ +-----------+ +-----------+
編輯:
從技術上講,我可以避免這樣的事情,但是當同時使用DAO且有許多servlet需要升級時,這很麻煩。
//In Servlet 1
@PersistenceContext(unitName="x")
EntityManager em;
@Inject
DaoA daoA;
@Inject
DaoB daoB;
@Postconstruct
public void postConstruct() {
daoA.setEm(em);
daoB.setEm(em);
}
//In Servlet 2
@PersistenceContext(unitName="y")
EntityManage r em;
@Inject
DaoA daoA;
@Postconstruct
public void postConstruct() {
daoA.setEm(em);
}
我假設當您要在Servlet中進行決策時,您的DAO應該在整個請求中使用相同的實體管理器,因為請求在Servlet中開始和結束。 換句話說,在處理http請求時,應僅使用一個實體管理器。
在這種情況下,您可以使用內置的請求范圍和CDI事件機制 。 為請求的作用域創建EM的生產器,以便每次使用新請求重新創建它。 然后,您可以使用特定的entityManager作為參數來觸發事件,生產者將觀察到該事件。 生產者收到事件后,它將存儲EM並將其作為生產價值返回。
執行方案:
EntityManager em
被注入到servlet中 emEvent
被注入到servlet中 @PostConstruct
或在服務方法的開頭,通過emEvent.fire(em)
觸發事件 EntityManager
EntityManager
@SessionScoped
@RequestScoped
, @SessionScoped
)。 否則,將在接收到任何事件之前調用實體管理器的生產者。 但是我相信這也適用於您問題中的簡單解決方案。 代碼示例:
//In Servlet 1
@PersistenceContext(unitName="x")
EntityManager em;
@Inject
Event<EntityManager> emEvent;
@Inject
Instance<DaoA> daoAInstance;
@Postconstruct
public void postConstruct() {
emEvent.fire(em);
daoAInstance.get().find(...); /* at this point, proper EM will be injected into DaoA.
You should access daoA only after emEvent is fired*/
}
// in producer
@RequestScoped (producer will be recreated for every request)
public class DynamicEMProducer {
EntityManager em; /* not injected, but set in observer method.
You may inject a default em if you wish using @PersistenceContext */
// this is handler of event fired in the servlet
public void emChanged(@Observes EntityManager em) {
this.em = em;
}
@Produces
public EntityManager produce() {
return em;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.