如何确保@Async方法中存在@Entity?

时间:2015-09-03 07:04:12

标签: java spring hibernate asynchronous

我想创建一个实体,并在事务中触发@Async方法对同一实体执行某些更改。这些更改也应该保持异步。

问题:因为我必须在事务中触发异步方法,所以我可以使用实体中自动生成的@Id。但是异步方法则必须首先通过该Id获取实体,并且通常这不存在。

只有当我在async方法中放置一些Thread.sleep()作为第一个语句时,才能确保实体已被外部事务持久化。

但是那个解决方案并不是很好。问题:如何在异步方法中确保它应该等待实体存在于DB中?

@Service
public class OuterService {
    @Service
    private SyncService service;

    @Transactional
    public void process() {
        service.mySyncMethod();
        //etc
    }
}

@Service
public class SyncService {
    @Transactional
    public void mySnycMethod() {
        Entity entity = new MyEntity();
        //fill entity
        dao.save(entity);
        asyncService.performLongRunningTask(entity.getId());
    }
}

@Service
public class AsycnService {
    @Async
    @Transactional
    public voi performLongRunningTask(Long id) {
        //problem: is mostly == null because this is executed before the outer transaction completes
        //only works if I put like Thread.sleep(5000) in between. but how can I really ensure the entity exists before executing this async lookup?
        MyEntity entity = dao.findOne(id);

        //perform long running task
        //change some fields in entity accordingly
        dao.save(entity);
    }
}

1 个答案:

答案 0 :(得分:1)

您可以使用TransactionSynchronizationManager.registerSynchronization()在事务提交上注册一个挂钩并实现afterCommit()方法。

@Transactional
public void mySnycMethod() {
    Entity entity = new MyEntity();
    // fill entity
    dao.save(entity);
    // performLongRunningTask will start after the transaction has been
    // commited
    TransactionSynchronizationManager
            .registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    asyncService.performLongRunningTask(entity.getId());
                }
            });

}

但请注意Javadocs在您的应用程序中使用TransactionSynchronizationManager所说的内容:

  

由资源管理代码使用,但不是由典型应用程序使用   代码