首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >检测AutoCloseable close()中的异常

检测AutoCloseable close()中的异常
EN

Stack Overflow用户
提问于 2011-12-04 23:19:05
回答 3查看 1.4K关注 0票数 10

我想构建一个自定义的AutoCloseable类,这样我就可以将以下代码转换为:

代码语言:javascript
复制
try {
    begin();
    doThings();
    commit();
} finally {
    if (transactionIsActive()) rollback();
}

变得更容易

代码语言:javascript
复制
try (Transaction t = begin()) { // too bad I have to store it in t though I don't use it
    doThings();
}

在这里,Transaction将是AutoCloseable,而在close()中,它将根据需要提交或回滚事务。

但是要实现这一点,我需要在Transaction.close()中检测try块内部是否发生了异常,或者它是否正常完成。这到底有没有可能?

如果它需要从一个新的异常中解析堆栈跟踪,这是可以的。更简单的编程将值得它带来的微小的性能冲击。

EN

回答 3

Stack Overflow用户

发布于 2011-12-04 23:57:07

我能想到的最接近的方法仍然需要手动将事务的成功标记为块的最后一条语句:

代码语言:javascript
复制
class Transaction implements AutoCloseable {
    private boolean rollback = true;

    public void success() {
        rollback = false;
    }

    public void close() {
        if (rollback) doRollback();
        else doCommit();
        // …
    }
}

class Main {
    public static void main(String[] args) {
        try (Transaction t = new Transaction()) {
            doThings();
            t.success();
        }
    }
}
票数 6
EN

Stack Overflow用户

发布于 2012-09-21 21:54:28

尽管我的代码与您的不同,但我也有类似的需求,即自动提交(大多数)事务并在出错时进行回滚。

大多数时候,我的代码中都有一些简单的查询,这些查询会自动回滚,如下所示:

代码语言:javascript
复制
try(Transaction t : database.beginTransaction()) {
  return t.selectUnique(Employee.class, "id=?", 200);
}  // implicit rollback here

有些数据库不喜欢像这样回滚查询,所以我通过区分“写”和“读”事务解决了这个问题。如果是读事务,close()将提交它,否则将回滚。它还将检查您在创建只读事务时没有执行任何写入操作。所以现在我可以写:

代码语言:javascript
复制
try(Transaction t : database.beginReadOnlyTransaction()) {
  return t.selectUnique(Employee.class, "id=?", 200);
}  // implicit commit here

写事务在结束时仍然需要调用提交本身,但这只是少数情况。

我知道这不是你想要的,但也许它仍然有用。

票数 1
EN

Stack Overflow用户

发布于 2014-07-30 04:24:02

我所能得到的最接近的结果就是显式地调用commit(),并假设任何没有这样做就退出事务块的代码都应该回滚。这与其他语言中的事务是一致的。虽然您可以忘记调用commit() (就像我经常做的那样),但至少这部分代码很可能会被测试。而且,不可能忘记在异常时回滚,这不太可能有测试覆盖率。

这类似于millimoose的设置标志的想法:

代码语言:javascript
复制
try (Transaction t = new Transaction()) {
    doThings();
    t.success();
}

除了您只使用活动状态作为标志。相同数量的代码,不需要新的标志。这假设任何没有显式调用commit()的事务都应该回滚,结果代码如下:

代码语言:javascript
复制
try (Transaction t = new Transaction()) {
    doThings();
    t.commit(); // marks the transaction as successful...
}

class Transaction implements AutoCloseable {
    public void close() {
        if (isActive())
            doRollback();
    }

    ...
}

我仍然不敢相信在核心语言中没有一个更干净的解决方案。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8376260

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档