什么是在Java中完成事务的正确代码模式(异常回滚和成功提交)?

Wil*_*zyr 7 java transactions exception-handling exception

我正在寻找通用代码模式来正确处理可能异常的事务.我假设有一个共同的代码模式,无论我们处理什么样的交易.

我有一个方法在事务中执行某些事情,并希望重新抛出在事务代码块内部可能发生的异常.以下是此类方法的示例:

protected void doIt() {
  // for JDBC connection transaction may be started automatically
  // but assume we start it here
  Tran tran = session.beginTran();
  try {
    // here comes code that does some processing
    // modifies some data in transaction
    // etc.

    // success - so commit
    tran.commit();

  } catch (Exception ex) { // many different exceptions may be thrown
                           // subclass of RuntimeException, SQLException etc.
     // error - so rollback
     tran.rollback();

     // now rethrow ex
     throw ex;              // this line causes trouble, see description below
  }      
}
Run Code Online (Sandbox Code Playgroud)

现在 - 方法中存在编译错误doIt.它必须声明,throws Exception但这是不可接受的,因为doIt在许多地方使用方法,并throws Exception在直接和间接使用的地方添加导致后续修改doIt.这是因为已知的Java语言设计问题与声明的异常.

现在的问题是:如何更改异常与事务处理代码以实现我的目标 - 正确处理事务完成(基于成功条件执行提交或回滚)并重新抛出可能在事务代码块中捕获的完全相同的异常.

我知道我可以做类似的事情,throw new RuntimeException(ex)但这会引发其他类的异常,我想避免这样的解决方案.

fal*_*tro 8

我会选择这样的东西.

protected void doIt() {
  // for JDBC connection transaction may be started automatically
  // but assume we start it here
  Tran tran = session.beginTran();
  bool success = false;
  try {
    // here comes code that does some processing
    // modifies some data in transaction
    // etc.

    // success - so commit
    tran.commit();
    success = true;
  } finally { 
     // error - so rollback
     if (! success)
       tran.rollback();
  }      
}
Run Code Online (Sandbox Code Playgroud)

..或者如果tran有一个方法可以查询状态(tran.isFinished())或其他东西,你不需要bool.任何抛出的异常(即运行时异常或错误,如果没有已检查的异常)将只是继续执行,在堆栈上执行finally块.

如果rollback抛出异常,你将需要捕获那些和log-em或其他东西(失败的回滚是一个非常严重的情况).记住在这种情况下不要抛出任何东西,因为当前展开堆栈的异常将丢失.