提交异步任务后,无法查询数据库数据问题
Spring事务同步:TransactionSynchronizationManager.registerSynchronization详解
问题场景
在Spring事务管理中,我们经常需要在事务提交后执行一些特定操作,比如发送消息、清理缓存或触发异步任务。但直接在这些操作可能会在事务未提交时执行,导致数据不一致问题。
解决方案
Spring提供了TransactionSynchronizationManager.registerSynchronization方法,允许我们在事务生命周期的特定点注册回调。
核心代码示例
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {@Overridepublic void afterCommit() {// 事务提交后执行self.asyncSubmitUpgradeTask(sysSchoolUpdate);}@Overridepublic void afterCompletion(int status) {// 事务完成后执行(无论提交还是回滚)if (status == STATUS_COMMITTED) {System.out.println("事务已提交");} else if (status == STATUS_ROLLED_BACK) {System.out.println("事务已回滚");}}
});
关键点解析
1. 方法说明
- afterCommit(): 仅在事务成功提交后执行
- afterCompletion(): 事务完成后执行(包括提交和回滚)
2. 使用场景
- 事务提交后发送消息通知
- 更新缓存或搜索引擎索引
- 触发异步处理任务
- 执行后续业务逻辑
3. 注意事项
- 必须在事务内调用,否则同步器会立即执行
- 使用代理对象(如示例中的
self)避免自调用问题 - 回调中不要执行耗时操作,以免阻塞事务完成
实际应用
@Service
public class SchoolService {@Autowiredprivate ApplicationContext applicationContext;@Transactionalpublic void updateSchool(SysSchoolUpdate sysSchoolUpdate) {// 更新数据库schoolRepository.update(sysSchoolUpdate);// 注册事务同步TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {@Overridepublic void afterCommit() {// 通过应用上下文获取代理beanSchoolService self = applicationContext.getBean(SchoolService.class);self.asyncSubmitUpgradeTask(sysSchoolUpdate);}});}@Asyncpublic void asyncSubmitUpgradeTask(SysSchoolUpdate sysSchoolUpdate) {// 异步处理任务// 这里可以安全地执行事务提交后的操作}
}
总结
TransactionSynchronizationManager.registerSynchronization是Spring事务管理中的重要工具,能够确保特定操作在事务正确提交后执行,是解决事务边界外操作的有效方案。
