这是我到目前为止所尝试的内容。
我向我的单身人士做了两次请求。第一个请求由方法firstRequest处理,它更改数据库。第二个请求由方法secondRequest处理,但它不会更改数据库。
@Singleton
public class App{
@Inject DaoHuman daoHuman;
Human human;
public void firstRequest(){
human= daoHuman.findById(1);
human.setAge(3);
}
public void secondRequest(){
human.setAge(99);
}
@Stateful
public class DaoHuman{
@PersistenceContext(unitName = "myPU", type=PersistenceContextType.EXTENDED)
private EntityManager em;
我的问题是第一次请求后实体变得分离(非托管)。所以它永远不会得到第二个请求。
答案 0 :(得分:0)
你有一个为你的有状态会话Bean定义的扩展持久化上下文,实际上在daoHuman.findById(1)
之后(未显示此代码,但我认为它是em.find(Humand.class, id))
被调用,人类ID = 1 1将成为一个托管实体,并由扩展的持久化上下文跟踪。
此外,因为您有一个扩展持久性上下文,所以此上下文将持续有状态会话Bean的生命周期,并且在多个客户端调用(对话)期间将保持对人类实体的管理。 p>
这一切都很好。但是,您的Singleton是无状态的,因此当您发出第二个请求时,人类不会被初始化。
您还必须记住,在对定义了EntityManager的有状态会话Bean进行调用时,扩展持久性上下文将仅与当前事务关联。 secondRequest()
不会发生这种情况,因此当事务完成时,不会将持久化上下文刷新/持久保存到数据库。
跨多个调用使用托管实例的一种简单方法是在首次初始化bean时将实体存储在有状态会话Bean实例上。 我在下面的代码中保留了单例/有状态会话bean结构。根据要求,我很想在会话bean上进行实体更新。
@Singleton
public class App{
@Inject DaoHuman daoHuman;
Human human;
Public void init(int humanId){
daoHuman.init(humanId);
}
public void firstRequest(){
// Making the call to daoHuman.getHuman() both returns the mnaged entity and
// causes the persistence context to be associated with the current
// transation, so when this method call ends, the context will be
// Depending on requirementsflushed/committed.
human= daoHuman.getHuman();
human.setAge(3);
}
public void secondRequest(){
human= daoHuman.getHuman();
human.setAge(99);
}
@Stateful
public class DaoHuman{
@PersistenceContext(unitName = "myPU", type=PersistenceContextType.EXTENDED)
private EntityManager em;
Human human;
public void Init(int humanId){
// em.find() will ensure the found entity becomes managed - part of the
// persistene context, placing it on the instance variable ensures
// the managed entity is available over multple client invocatons (converstion)
human = em.find(Human.class, humanId)
}
public Human getHuman(){
return human;
}