【问题标题】:How to pass a JPA entity to an Asynchronous EJB method如何将 JPA 实体传递给异步 EJB 方法
【发布时间】:2018-11-09 13:11:34
【问题描述】:

在处理请求时,我想根据接收并存储在数据库中的数据在单独的事务中“启动”单独的任务。 主要优点是我可以在所有附加处理完成之前将结果返回给我的请求,而且如果附加处理失败,这不会影响请求的原始处理(因为它们在不同的事务中)。这种额外的处理可能需要向数据添加额外的信息。

我有以下设置。在使用@Asynchronous 的地方创建了附加任务。

@Stateless
public class Bean1
{
    @EJB 
    Bean2 bean2;

    @PersistenceContext
    private EntityManager entityManager;

    public MyResult doSomething(MyInput input) {
        MyEntity myEntity = new MyEntity();
        // Fill data based on input
        entityManager.persist(myEntity);

        bean2.asyncActOnData(myEntity);
        // Perhaps do some more work and return result
    }
}

@Stateless
public class Bean2
{
    @Asynchronous // This causes a new transaction to happen
    public void asyncActOnData(MyInput input){
         // Act upon data and store result in DB
    }
}

这似乎是一种干净的方式,但是这会导致 JPA 实体分离,可能是在 Bean2 的处理过程中。

目前我不打算在持久调用(和 asnyc)之后更改数据,但随着应用程序的增长,我觉得允许这样做以避免错误会更安全。

根据持久数据启动单独的异步任务的正确方法是什么?

我正在使用:Java EE 6 和 Eclipselink 2.5.2 for JPA。

【问题讨论】:

    标签: java jpa jakarta-ee ejb


    【解决方案1】:

    您可以继续使用分离的实例,前提是:

    1. 您不打算执行进一步的持久性操作;

    2. 在调用asyncActOnData 时,所有关联实体(如果有)都可用。

    但是,如果您需要执行进一步的持久化操作,您可以执行以下操作:

    @Stateless
    public class Bean1
    {
        @EJB 
        Bean2 bean2;
    
        @PersistenceContext
        private EntityManager entityManager;
    
        public MyResult doSomething(MyInput input) {
            MyEntity myEntity = new MyEntity();
            // Fill data based on input
            entityManager.persist(myEntity);
    
            // Flush the persistence context and detach the entity
            // An entity is not permitted to be in more than one
            // persistence context at a time. This should prevent
            // a race condition with the merge in bean2.
            entityManager.flush();
            entityManager.detach(myEntity);
            Future<Result> futureResult = bean2.asyncActOnData(myEntity);
    
            // Perhaps do some more work and return result
            ....
    
            return futureResult.get();
        }
    }
    
    @Stateless
    public class Bean2 {
    
        @PersistenceContext
        private EntityManager entityManager;
    
        @Asynchronous
        public Future<Result> asyncActOnData(MyInput input) {
             // this will ensure that the database still matches input
             // and add input into the persistence context
             input = entityManager.merge(input);
             ...
             return new javax.ejb.AsyncResult<Result>(result);
        }
    
    }
    

    您会发现阅读“Java™ Persistence API,版本 2.1”规范的第 3.2 节很有用。

    【讨论】:

    • 你的意思是合并和刷新吗?似乎在分离的对象上不允许仅刷新 (en.wikibooks.org/wiki/Java_Persistence/Persisting#Refresh)。进行合并然后刷新实际上可能会将其重置为数据库状态。虽然如果刷新发生在 Bean1 中的提交之前,它可能会失败?
    • 看来我看错了规范。很抱歉,正如我所打算的那样/或。看来merge 是唯一的出路。
    • 请注意,我认为您需要在调用asyncActOnData之前故意分离实体
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多