2017-02-15 43 views
0

我有使用TransactionSynchronization.afterCommit代碼通過TransactionSynchronizationManager.registerSynchronization(...)一個事務裏交易inside` TransactionSynchronizationManager` afterCommit與TaskExecutor的

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。

回答

0

當調用#afterCommit()方法時,Spring可能仍然會看到上下文被綁定到一個已有的事務,只是事務已經被調用;因此爲什麼你看到它可能是活躍的。

根據方法here的javadoc,如果您希望允許其他代碼運行需要事務,則需要強制Spring生成新的傳播事務。所以改變你的Manager#save方法如下:

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

它的工作!但是我不明白的是,爲什麼只用'@ Transactional'在Spring MVC上下文中工作?我認爲它也應該在TaskExecutor上下文中工作。 – Bruno