我必须将数据保存到2个不同的表中。我需要它是全有或全无的交易。如果第二笔交易失败,我该如何回滚第一笔交易?
在下面的代码中,我按以下顺序执行storeToTable1()和storeToTable2()。
如果storeToTable2()失败,我希望storeToTable1()回滚。
配置类:
class StoreToDBConfig {
@Bean
public IntegrationFlow receiveMessage() {
return IntegrationFlows
.from("inputChannel")
.transform("convertToTable1Format")
.handle(ServicetoDBAdaptor,"storeToTable1")
.transform("convertToTable2Format")
.handle(ServicetoDBAdaptor,"storeToTable2")
.get();
}
}
对数据库适配器的服务:
class ServicetoDBAdaptor {
@Autowired
UserExecutionDetail userExecutionDetail;
@Autowired
UserExecution userExecution;
@Autowired
UserExecutionDetailRepository userExecutionDetailRepository;
@Autowired
UserExecutionRepository userExecutionRepository;
@Transactional(propagation=Propagation.REQUIRED)
@ServiceActivator
private void storeToTable1(Message<UserExecutionDetail> msg) throws Exception {
userExecutionDetailRepository.save(msg.getPayload());
}
@Transactional(propagation=Propagation.REQUIRED)
@ServiceActivator
private void storeToTable2(Message<UserExecution> msg) throws Exception {
userExecutionRepository.save(msg.getPayload());
}
}
答案 0 :(得分:2)
为此,您需要在第一个handle()
上使用类似这样的内容:
.handle(ServicetoDBAdaptor,"storeToTable1", e -> e.transactional(true))
此钩子将完全执行此操作:
/**
* Specify a {@link TransactionInterceptor} {@link Advice} with default
* {@code PlatformTransactionManager} and {@link DefaultTransactionAttribute} for the
* {@link MessageHandler}.
* @param handleMessageAdvice the flag to indicate the target {@link Advice} type:
* {@code false} - regular {@link TransactionInterceptor}; {@code true} -
* {@link org.springframework.integration.transaction.TransactionHandleMessageAdvice}
* extension.
* @return the spec.
*/
public S transactional(boolean handleMessageAdvice) {
我们将在哪里使用这个
/**
* A {@link TransactionInterceptor} extension with {@link HandleMessageAdvice} marker.
* <p>
* When this {@link Advice} is used from the {@code request-handler-advice-chain}, it is applied
* to the {@link MessageHandler#handleMessage}
* (not to the
* {@link org.springframework.integration.handler.AbstractReplyProducingMessageHandler.RequestHandler#handleRequestMessage}),
* therefore the entire downstream process is wrapped to the transaction.
* <p>
* In any other cases it is operated as a regular {@link TransactionInterceptor}.
*
* @author Artem Bilan
*
* @since 5.0
*/
@SuppressWarnings("serial")
public class TransactionHandleMessageAdvice extends TransactionInterceptor implements HandleMessageAdvice {
这里的关键是the entire downstream process is wrapped to the transaction.
。
因此,交易将从您的storeToTable1()
开始,并且交易会一直扩展到流程结束,而您的storeToTable2()
将参与同一TX。因此,当那个被回滚时,第一个也将被回滚。只是因为您根本只有一笔交易!