【发布时间】:2015-11-28 21:34:16
【问题描述】:
我想创建一个实体,并在事务中触发@Async 方法来对同一实体执行一些更改。更改也应该保持异步。
问题:由于我必须在事务中触发异步方法,我可以使用从实体自动生成的@Id。但是 async 方法必须首先通过该 Id 获取实体,而且大多数情况下这还不存在。
只有当我在异步方法中放入一些Thread.sleep()作为第一条语句时,才能确保实体已被外部事务持久化。
但是那个解决方案不是很好。问题:如何确保在异步方法内部它应该等待实体存在于数据库中?
@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);
}
}
【问题讨论】:
-
使您的
OuterService不是事务性的,并将对AsyncService.performLongRunningTask的调用移至该位置。这确保了事务已经完成并且实体在数据库中。 -
那么传递分离的实体而不是 id 是否有意义,以将 dao 查找保存在异步方法中?
-
您仍然需要重新附加它,因为会话不再有效。我会简单地传递 ID。
-
好的,谢谢。无论如何,我可能无法使
OuterService不是事务性的,因为在导致问题的特定调用之前和之后有很多逻辑(还有必须参与 tx 的数据库/dao 调用)...... -
然后将所有这些调用包装在事务中,而不是对异步内容的调用。您可以将其移动到可以注释事务的不同类。您只需要在调用异步方法之前确保事务已提交。想办法做到这一点。
标签: java spring hibernate asynchronous