我有一条路线
from("direct:my-route")
.routeId("id")
.process(log(...))
.transacted() // Begin transaction
.bean(...)
.bean(...)
.process(...)
.bean(...)
.to("direct:end"); // End transaction
如您所见,正在交易中。在Beans
或Processors
内部使用JdbcTemplate
执行的所有操作都将被处理。
我们有一个自定义的ErrorHandler
,它扩展了DeadLetterChannel
,我注意到当引发异常时,无论如何都会进行事务处理。
在TransactionTemplate#execute
内
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
result = action.doInTransaction(status);
}
catch (RuntimeException | Error ex) {
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Throwable ex) {
// Transactional code threw unexpected exception -> rollback
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallbac
}
this.transactionManager.commit(status); <--- after doInTransaction
return result;
调用action.doInTransaction(status);
之后,即使我抛出了通用的this.transactionManager.commit(status)
,代码流也只会进入RuntimeException
。
对action.doInTransaction(status)
的调用转到了TransactionErrorHandler
,特别是这段代码
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
// wrapper exception to throw if the exchange failed
// IMPORTANT: Must be a runtime exception to let Spring regard it as to do "rollback"
RuntimeException rce;
// and now let process the exchange by the error handler
processByErrorHandler(exchange);
// after handling and still an exception or marked as rollback only then rollback
if (exchange.getException() != null || exchange.isRollbackOnly()) {
...
processByErrorHandler
只需将Exchange
的例外设置为null
,所以它不会被重新抛出。
抱歉,此“令人困惑”的简介。我的问题是,在出现异常的情况下如何显式回滚事务?这里有什么更好的策略?