Spring事务:在Exception或Throwable上回滚

时间:2014-01-17 14:28:41

标签: java spring transactions

我想知道使用而不是

是否有意义
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)

使用Throwable

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)

据我了解,即使遇到非常糟糕的事情,抓住Error也会帮助我们正确行事。或者也许没有用?

4 个答案:

答案 0 :(得分:17)

  

据我所知,捕捉错误将帮助我们正确行事,即使发生了非常糟糕的事情。或者也许没有用?

您不需要显式指定rollbackFor = Throwable.class,因为如果发生Error,spring将默认回滚事务。

请参阅12.5.3 Rolling back a declarative transaction

  

在默认配置中,Spring Framework的事务基础结构代码仅在运行时未经检查的异常情况下标记用于回滚的事务;也就是说,抛出的异常是RuntimeException的实例或子类。 (错误也会 - 默认情况下会导致回滚)。从事务方法抛出的已检查异常不会导致在默认配置中回滚。

或者查看DefaultTransactionAttribute

public boolean rollbackOn(Throwable ex) {
    return (ex instanceof RuntimeException || ex instanceof Error);
}

答案 1 :(得分:4)

由于您使用的是@Transactional,我们可以放心地假设您正在通过Spring,Hibernate或其他JDBC包装器进行数据库操作。这些JDBC包装器通常不会抛出已检查的异常,它们会抛出包含JDBC SQLException类型的运行时异常。

默认情况下,

@Transactional设置为仅在抛出未经检查的异常时回滚。

考虑像这样的用例

@Transactional
public void persistAndWrite(Bean someBean) throws IOException{
    getSession().save(someBean); // DB operation
    someFileService.writeToFile(someBean); File IO operation which throws IOException
}

您不一定要回滚数据库操作,因为我们无法将某些内容写入文件。

类似地

@Transactional
public void persistAndThrowOutOfMemory(Bean someBean)  {
    getSession().save(someBean); // DB operation
    someService.hugeOperationThrowsOutOfMemoryError(); // consumes all memory, throws OutOfMemoryError
}

您不一定要回滚已保存的实体,因为某些服务会导致消耗太多内存。

@Transactional为您提供选项。在适当的地方使用它。

答案 2 :(得分:0)

我不知道是否可能但是处理像Throwable这样的Error是一种糟糕的编程风格,处理这种致命错误并不是开发人员的责任。总是会发生你无法处理的坏事。您应该在必要时处理已检查的异常,这些异常是系统已知的,如某种类型的逻辑错误。

答案 3 :(得分:0)

回滚的默认值是在发生错误异常时进行注册,但是当您手动注册try{}catch{}时,它将覆盖错误,因此在这种情况下,请使用

catch {
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
      }

手动执行或删除尝试捕获

您还可以在事务注释中注册异常类型,例如:

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)