有一个逻辑希望事务提交后才去执行,具体实现如下
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这里再包装了一层,使他可以异步调用
网友评论