java CDI:在“注入链”中生成正确EntityManager的好方法
我有很多Servlet,我正在从使用PersistenceContext重写为使用@Injected DAO
在JSF中,我可以在@products方法中获取对FacesContext的引用,并根据登录用户返回正确的EM(或者使用默认值,如果登录,有效用户可用)
当我必须为注入到不同Servlet中的相同DAO生成不同的EMs,并且要注入的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);
}
# 1 楼答案
我假设,当您想要在servlet中做出决定时,DAO应该在整个请求中使用相同的实体管理器,因为请求在servlet中开始和结束。换句话说,在服务http请求时,只应使用一个实体管理器
在这种情况下,可以使用内置的请求范围和CDI event mechanism。为EM创建一个producer,该producer的作用域为request,这样每次都会用一个新请求重新创建它。然后,您可以使用特定的entityManager作为参数触发一个事件,该参数由您的生产者观察。当生产者收到事件时,它将存储EM并将其作为生产值返回
执行模式:
EntityManager em
被注入servletemEvent
被注入servlet@PostConstruct
中还是在服务方法的开始,通过emEvent.fire(em)
触发事件EntityManager
EntityManager
@RequestScoped
,@SessionScoped
)。否则,将在收到任何活动之前致电实体经理的制作人。但我相信这也适用于你的问题的简单解决方案李>代码示例: