jpa+ejb 如何为多个请求保持实体附加(托管)?
jpa+ejb how to keep entity attached (managed) for multiple requests?
这是我到目前为止尝试过的方法。
我对我的单身人士提出了 2 个请求。第一个请求由方法 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;
我的问题是实体在第一次请求后变得分离(非托管)。所以它永远不会得到第二个请求。
您有一个为有状态会话 Bean 定义的扩展持久性上下文,确实在 daoHuman.findById(1)
之后(此代码未显示,但我假设它是 em.find(Humand.class, id))
被调用,人类Id=1 将成为托管实体并由扩展持久性上下文跟踪。
此外,因为您有一个 Extended 持久化上下文,这个上下文将在有状态会话 Bean 的生命周期内持续存在,并且人类实体将在多个客户端调用期间保持受管理(对话)。
一切都很好。然而,你的单例是无状态的,所以当你发出第二个请求时,human 没有被初始化。
您还必须牢记,只有在调用定义了 EntityManager 的有状态会话 Bean 时,您的扩展持久性上下文才会与当前事务相关联。 secondRequest()
不会发生这种情况,因此当事务完成时,没有持久性上下文 flushed/persisted 到数据库。
跨多个调用使用托管实例的一种简单方法是在 Bean 首次初始化时将实体存储在有状态会话 Bean 实例上。
我在下面的代码中为您保留了 singleton/Stateful 会话 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;
}
这是我到目前为止尝试过的方法。
我对我的单身人士提出了 2 个请求。第一个请求由方法 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;
我的问题是实体在第一次请求后变得分离(非托管)。所以它永远不会得到第二个请求。
您有一个为有状态会话 Bean 定义的扩展持久性上下文,确实在 daoHuman.findById(1)
之后(此代码未显示,但我假设它是 em.find(Humand.class, id))
被调用,人类Id=1 将成为托管实体并由扩展持久性上下文跟踪。
此外,因为您有一个 Extended 持久化上下文,这个上下文将在有状态会话 Bean 的生命周期内持续存在,并且人类实体将在多个客户端调用期间保持受管理(对话)。
一切都很好。然而,你的单例是无状态的,所以当你发出第二个请求时,human 没有被初始化。
您还必须牢记,只有在调用定义了 EntityManager 的有状态会话 Bean 时,您的扩展持久性上下文才会与当前事务相关联。 secondRequest()
不会发生这种情况,因此当事务完成时,没有持久性上下文 flushed/persisted 到数据库。
跨多个调用使用托管实例的一种简单方法是在 Bean 首次初始化时将实体存储在有状态会话 Bean 实例上。 我在下面的代码中为您保留了 singleton/Stateful 会话 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;
}