我在交易中使用InfiniteLoader
到TransactionSynchronization.afterCommit
的代码:
TransactionSynchronizationManager.registerSynchronization(...)
在afterCommit代码中调用TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
Manager.save(param)
}
});
的方法:
@Transactional
我使用Spring,Hibernate和EntityManagerFactory,这个代码在Spring MVC中运行时运行良好,否则,当发出Web请求但是在TaskExecutor(public class ManagerImpl implements Manager {
@Transactional
public void save(...) { ... }
}
)内运行时我得到错误:
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()
检查了交易,然后返回true。
答案 0 :(得分:0)
当调用#afterCommit()
方法时,Spring仍然可以看到上下文绑定到现有事务,只是事务已经被调用;因此,为什么你看到它可能是活跃的。
根据方法here的javadoc,如果您想要允许其他代码运行需要事务,则需要强制Spring生成新的传播事务。因此,请按以下方式更改Manager#save
方法:
public class ManagerImpl implements Manager {
@Transactional(propagation = PROPAGATION_REQUIRES_NEW)
public void save( ... ) {
}
}
答案 1 :(得分:0)
这仅在负责管理事务的 PlatformTransactionManager
类能够区分处于已完成状态的旧事务和在 TransactionSynchronization
中启动的新事务时才有效.
PlatformTransactionManager
这样的 HibernateTransactionManager
类无法在所有情况下强制执行此操作。这主要是因为 HibernateTransactionManager
通过 Session
将 Hibernate Transaction
与 SessionHolder
实例联系起来。 SessionHolder
实例缓存在线程局部变量中。在同一线程中启动新事务时,HibernateTransactionManager
检索与该线程关联的 SessionHolder
,以重用事务和 Hibernate 会话。
在正常情况下,这不是什么大问题,因为线程本地缓存在事务提交或回滚时被清除。但是,在 TransactionSynchronization
中,线程本地值尚未清除,因此会阻止初始化新事务,除非明确进行初始化。
有很多方法可以解决这个问题:
@Async
注释的方法来包装作品。