Spring事务:在Exception或Throwable上回滚

Igo*_*nko 10 java spring transactions

我想知道用它代替是否有意义

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
Run Code Online (Sandbox Code Playgroud)

使用 Throwable

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
Run Code Online (Sandbox Code Playgroud)

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

Ren*_*ink 26

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

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

请参见12.5.3回滚声明性事务

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

或者看看 DefaultTransactionAttribute

public boolean rollbackOn(Throwable ex) {
    return (ex instanceof RuntimeException || ex instanceof Error);
}
Run Code Online (Sandbox Code Playgroud)


Sot*_*lis 10

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

@Transactional 默认情况下,设置为仅在引发未经检查的异常时回滚。

考虑这样的用例

@Transactional
public void persistAndWrite(Bean someBean) throws IOException {
    // DB operation
    getSession().save(someBean); 

    // File IO operation which throws IOException
    someFileService.writeToFile(someBean); 
}
Run Code Online (Sandbox Code Playgroud)

您不一定会因为我们无法向文件写入内容而想要回滚数据库操作。

相似地

@Transactional
public void persistAndThrowOutOfMemory(Bean someBean)  {
    // DB operation
    getSession().save(someBean);

    // consumes all memory, throws OutOfMemoryError
    someService.hugeOperationThrowsOutOfMemoryError(); 
}
Run Code Online (Sandbox Code Playgroud)

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

@Transactional给你选择。在适当的地方使用它。

  • 如果我将此方法标记为事务 - 那么我确定我想回滚一些硬错误。但是如果它通常会起作用并被认为是好的做法? (3认同)
  • 但默认情况下,事务也会在“错误”时回滚。至少 JTA 和 Spring 都会在“RuntimeException”和“Error”上回滚,除非您显式指定“dontRollbackOn=Error.class”。 (2认同)