我正在寻找通用代码模式来正确处理可能异常的事务.我假设有一个共同的代码模式,无论我们处理什么样的交易.
我有一个方法在事务中执行某些事情,并希望重新抛出在事务代码块内部可能发生的异常.以下是此类方法的示例:
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 } }
现在 – 方法doIt中存在编译错误.它必须声明throws Exception但这是不可接受的,因为方法doIt在很多地方使用并添加throws Exception导致在直接和间接使用doIt的地方进行后续修改.这是因为已知的Java语言设计问题与声明的异常.
现在的问题是:如何更改异常与事务处理代码以实现我的目标 – 正确处理事务完成(基于成功条件执行提交或回滚)并重新抛出可能在事务代码块中捕获的完全相同的异常.
我知道我可以做一些像抛出新的RuntimeException(ex)但这会抛出其他类的异常,我想避免这样的解决方案.
解决方法
我会选择这样的东西.
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(); } }
..或者如果tran有一个方法可以查询状态(tran.isFinished())或其他东西,你不需要bool.任何抛出的异常(即运行时异常或错误,如果没有已检查的异常)都会直接执行,在堆栈上执行finally块.
如果rollback抛出异常,你将需要捕获那些和log-em或其他东西(失败的回滚是一个非常严重的情况).记住在这种情况下不要抛出任何东西,因为当前展开堆栈的异常将丢失.