最近遇到个case,在事务控制下insert,过程中会发生http API调用,发生任何异常情况,直接回滚。
然而,http 连接timeout的情况下,insert 却成功了。
一直以为只要throw Exception,默认事务就会回滚,看了源码,才纠正了这个误解。
......
处理异常的实现:
/**
* Handle a throwable, completing the transaction.
* We may commit or roll back, depending on the configuration.
*/
protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.hasTransaction()) {
// 哪种Exception 会触发rollback ???
if (txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
// ...
} else {
// We don't roll back on this exception. 呃,还是会commit!!!
// Will still roll back if TransactionStatus.isRollbackOnly() is true.
try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
// ...
}
}
}
再看看哪种Exception会触发rollback
/**
* The default behavior is as with EJB: rollback on unchecked exception.
* Additionally attempt to rollback on Error.
* TransactionTemplate 默认支持.
*/
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
上述的情况怎么处理:
try...catch(ex) {打印error日志 && throw RuntimeException(...)}
......
总结:
默认事务回滚策略:throw RuntimeException 或者 Error。