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()
不可靠:/谢谢您提供的信息。