我想构建一个自定义的AutoCloseable类,这样我就可以将以下代码转换为:
try {
begin();
doThings();
commit();
} finally {
if (transactionIsActive()) rollback();
}变得更容易
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块内部是否发生了异常,或者它是否正常完成。这到底有没有可能?
如果它需要从一个新的异常中解析堆栈跟踪,这是可以的。更简单的编程将值得它带来的微小的性能冲击。
发布于 2011-12-04 23:57:07
我能想到的最接近的方法仍然需要手动将事务的成功标记为块的最后一条语句:
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();
}
}
}发布于 2012-09-21 21:54:28
尽管我的代码与您的不同,但我也有类似的需求,即自动提交(大多数)事务并在出错时进行回滚。
大多数时候,我的代码中都有一些简单的查询,这些查询会自动回滚,如下所示:
try(Transaction t : database.beginTransaction()) {
return t.selectUnique(Employee.class, "id=?", 200);
} // implicit rollback here有些数据库不喜欢像这样回滚查询,所以我通过区分“写”和“读”事务解决了这个问题。如果是读事务,close()将提交它,否则将回滚。它还将检查您在创建只读事务时没有执行任何写入操作。所以现在我可以写:
try(Transaction t : database.beginReadOnlyTransaction()) {
return t.selectUnique(Employee.class, "id=?", 200);
} // implicit commit here写事务在结束时仍然需要调用提交本身,但这只是少数情况。
我知道这不是你想要的,但也许它仍然有用。
发布于 2014-07-30 04:24:02
我所能得到的最接近的结果就是显式地调用commit(),并假设任何没有这样做就退出事务块的代码都应该回滚。这与其他语言中的事务是一致的。虽然您可以忘记调用commit() (就像我经常做的那样),但至少这部分代码很可能会被测试。而且,不可能忘记在异常时回滚,这不太可能有测试覆盖率。
这类似于millimoose的设置标志的想法:
try (Transaction t = new Transaction()) {
doThings();
t.success();
}除了您只使用活动状态作为标志。相同数量的代码,不需要新的标志。这假设任何没有显式调用commit()的事务都应该回滚,结果代码如下:
try (Transaction t = new Transaction()) {
doThings();
t.commit(); // marks the transaction as successful...
}
class Transaction implements AutoCloseable {
public void close() {
if (isActive())
doRollback();
}
...
}我仍然不敢相信在核心语言中没有一个更干净的解决方案。
https://stackoverflow.com/questions/8376260
复制相似问题