将在EJB上创建的注入EntityManager传递给将返回Object的方法是否安全,之后,为Web客户端在Web会话上保留该Object使用它?
就像在这个例子中一样: EJB
@Stateless(mappedName = "MyService")
@LocalBean
public class MyService implements MyServiceLocal {
@PersistenceContext(unitName="primary")
private EntityManager em;
/**
* Default constructor.
*/
public MyService() {
}
@Override
public Service newServiceX(User user) {
return new ServiceX(user,em); // here, passing the EntityManager
}
}
之后,我将此服务保留在Web客户端中(使用struts): 基本行动
public class YAction extends ActionSupport implements SessionAware{
@Inject
private MyServiceLocal service;
public String execute(){
Service x = service.newServiceX();
persistInCookie("ServiceX",x);
}
public void persistInCookie(String, Object){
// persist
}
}
然后,使用另一个动作: //另一个行动
class XAction{
public String useService(){
getService().doSomething();
}
protected Service getService(){
Service service = (Service) getSessionMap().get("ServiceX");
return service;
}
}
使用EntityManager的POJO类ServiceX:
public class ServiceX extends Service{
EntityManager em;
public ServiceX(User user, EntityManager em){
this.em = em;
}
public void doSomething(){
// do something with the EntityManager passed by the EJB
}
}
首先,要调用的操作是在会话上持久保存服务的Y操作,接下来,X操作将返回会话上持久保存的服务并尝试使用它。
我相信EJB无状态会话Bean可以关闭My EntityManager,而这个ServiceX POJO类不能使用它。这可能发生?我发现了类似的问题HERE,但在这个问题中,EntityManager被传递给一个帮助器类。在我的情况下是不同的,因为我想在会话cookie上保留此Object,并在以后使用。
答案 0 :(得分:1)
我认为在EntityManager
中存储SessionMap
不是一个好主意。更重要的是,我甚至认为在EJB容器外执行EntityManager
操作不是一个好主意。
已阅读JPA中的交易边界?
默认情况下,EJB容器使用 CMT (容器管理事务)。在这种情况下,容器使用 entitymanager-per-request模式,这意味着当MyService
的一个业务方法开始和结束时事务开始和结束(事务已提交或回滚以防万一) of RuntimeException)。对于整个事务时间,EntityManager
与相同的PersistenceContext连接。在事务结束后,容器关闭EntityManager
,这意味着EntityManager
与最近的PersistenceContext断开连接:
// transaction begins
Service x = service.newServiceX();
// transaction ends
如果您要在事务之外进行一些更新/插入操作,这可能是至关重要的。
现在,当您在事务外部调用EntityManager
操作(如find
)时,对于每个操作,EntityManager
将创建新的PersistentContext。这可能会导致一些问题,因为代表同一记录的两个实体将被视为不同的实体:
// each operation occurs in a separate persistence context, and returns
// a new detached instance
Magazine mag1 = em.find(Magazine.class, magId);
Magazine mag2 = em.find(Magazine.class, magId);
assertTrue(mag2 != mag1);
还有更多文章要阅读: