记一次TransactionSynchronization.afterCommit导致的事务异常问题

本文探讨了在使用Spring框架时,TransactionSynchronization.afterCommit方法调用导致的notransactionisinprogress异常问题。通过调整事务传播行为为PROPAGATION_REQUIRES_NEW或采用异步调用的方式,有效避免了此异常,确保了事务提交后逻辑的正确执行。

记一次TransactionSynchronization.afterCommit导致的no transaction is in progress问题

有一个逻辑希望事务提交后才去执行,具体实现如下

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  @Override
  public void afterCommit() {
    Manager.save(param)
  }
});

afterCommit 调用带有@Transaction的save方法

public class ManagerImpl implements Manager {
  @Transactional
  public void save(...) { ... }
}

web 调用后会报错

javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.checkTransactionNeeded(AbstractEntityManagerImpl.java:1171)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:1332)
at sun.reflect.GeneratedMethodAccessor2083.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:293)
at com.sun.proxy.$Proxy147.flush(Unknown Source)

查询资料发现:当#afterCommit()调用该方法时,Spring可能仍会看到上下文已绑定到现有事务。
如果想运行需要事务的其他代码,则需要强制Spring生成一个新的传播事务。因此Manager#save,所以需要更改方法:

public class ManagerImpl implements Manager {
  @Transactional(propagation = PROPAGATION_REQUIRES_NEW) 
  public void save( ... ) {
  }
}

propagation = PROPAGATION_REQUIRES_NEW很容易误用,不太建议。所以我在save这里再包装了一层,使他可以异步调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值