我想创建一个实体,并在事务中触发一个@Async
方法来对同一个实体执行一些更改。更改也应该持久化。
问题:由于我必须在事务中触发@Id
方法,我可以使用实体中自动生成的@Id
。但是,如果是这样的话,那么这个方法就必须首先通过这个ID来获取实体,而大多数情况下,这个ID还不存在。
只有当我把一些Thread.sleep()
作为第一个语句放在Thread.sleep()
方法中时,才能确保该实体已被外部事务持久化。
但这种解决方案并不好。问:我如何确保在DB2C方法中,它应该等待实体在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);
}
}
2条答案
按热度按时间dy2hfwbg1#
您可以使用
TransactionSynchronizationManager.registerSynchronization()
并实现afterCommit()
方法在事务提交时注册一个钩子。但是请注意Javadoc关于在应用程序中使用
TransactionSynchronizationManager
的说法:由资源管理代码使用,但不由典型应用程序代码使用
ffdz8vbo2#
我最终实现的解决方案是通过
ApplicationEvent
、ApplicationEventPublisher
和@ApplicationEventListener
与phase = AFTER_COMMIT
一起使用Spring应用程序事件。然后,在事务和实体持久化之后,将调用您的BRAC方法。