1

给定以下代码:我们需要锁定模型,然后启动一个事务(这可能会引发异常,因此我们必须确保释放锁),然后执行类似于获取数据库连接的操作(这可能会引发异常),然后做一些可能引发需要还原事务的异常的事情。这是 Java 6,所以我们没有可用的 Java 7 好东西。

SomeClass someMethod() 
throws SomeException {
  acquireWriteLock();
  try {
    startTransaction();
    try {
      DBConnection d = openDBConnection();
      try {
        doStuff(d);
        commitTransaction();
      } finally {
        d.close();
      }
    } catch (SomeException e) {
      handleSomeException(e);
      revertTransaction();
      throw e;
    } catch (Throwable t) {
      revertTransaction();  // Error: method must return a value of SomeClass
    }
  } finally {
    releaseWriteLock();
  }
}

可以将其重写为更具可读性和更少冗长吗?

只是为了好玩:当您看到以下内容时,您会怎么做?

DBConnection d = null;
try {
  acquireWriteLock();
  startTransaction();
  d = openDBConnection();
  try {
    doStuff(d);
    commitTransaction();
  } catch (SomeException e) {
    handleSomeException(e);
    revertTransaction();
  }
} finally {
  d.close();
  releaseWriteLock();
}
4

2 回答 2

2

如果您切换到 Java 7,则可以大大简化它。否则,您可能不需要做太多事情

可以尝试以下想法:

  • 将 DB 连接 + 事务管理 + 锁管理重构为通用基类中的通用方法,每个事务类型都有一个子类

  • 将DB连接+事务管理+锁管理重构为final类中的通用方法,事务类型有一个接口,每个有一个实现类。

然而,除非这种特定的模式被重复很多很多次,否则这种重构可能是一个坏主意。(您将创建一个本地成语,并且读者必须在含义变得清晰之前学习该成语。)

于 2012-06-11T00:26:49.470 回答
1

Without upgrading to Java 7 you can combine some of this so you only need a single try-catch.

SomeClass someMethod() throws SomeException {
   boolean committed = false;
   DBConnection d = null;
   acquireWriteLock();
   try {
      startTransaction();
      d = openDBConnection();
      doStuff(d);
      commitTransaction();
      committed = true;
   } catch (SomeException e) {
      handleSomeException(e);
      throw e;
   } finally {
     if( d != null ) d.close();
     if( !committed ) revertTransaction();
     releaseWriteLock();
   }
}

The trick is to make sure revertTransaction() and DBConnection.close() don't throw anything, but if you can't do that then you can put releaseWriteLock() in another finally clause. If you really wanted to improve this more you could do some of the refactorings Stephen C mentioned. Doing something like putting the acquire/release writeLock, start/rollback transaction, and open/close DBConnection are done in base class or some abstract operation class.

于 2012-06-11T00:49:38.727 回答