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;
}