Java 与TaskExecutor提交后,`TransactionSynchronizationManager`内的事务

Java 与TaskExecutor提交后,`TransactionSynchronizationManager`内的事务,java,spring,hibernate,spring-mvc,transactions,Java,Spring,Hibernate,Spring Mvc,Transactions,我有一个代码,在事务中使用TransactionSynchronization.afterCommit通过TransactionSynchronizationManager.registerSynchronization(…): TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() {

我有一个代码,在事务中使用
TransactionSynchronization.afterCommit
通过
TransactionSynchronizationManager.registerSynchronization(…)

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  @Override
  public void afterCommit() {
    Manager.save(param)
  }
});
在afterCommit中,代码被称为具有
@Transactional
的方法:

public class ManagerImpl implements Manager {
  @Transactional
  public void save(...) { ... }
}
我使用Spring、Hibernate和EntityManagerFactory,此代码在Spring MVC中运行时运行良好,否则,当出现web请求时,但在TaskExecutor(
org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
)中运行时,我得到错误:

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)
//called entityManager.flush()
我使用TransactionSynchronizationManager.isActualTransactionActive()检查了事务,它返回true。

当调用
#afterCommit()
方法时,Spring可能仍然看到上下文绑定到现有事务,只是事务已提交;因此,您看到它可能处于活动状态的原因

根据该方法的javadoc,如果希望允许其他需要事务的代码运行,则需要强制Spring生成新的传播事务。因此,请按如下方式更改您的
Manager#save
方法:

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

成功了!但我不明白的是,为什么在SpringMVC上下文中,它只使用
@Transactional
?我认为它也应该在TaskExecutor环境下工作。嗯,我今天花了几个小时才发现
TransactionSynchronizationManager.isActualTransactionActive()
不可靠:/谢谢您提供的信息。