我们编写了一个类,用于打开与服务器的连接。完成操作后,如果一切成功,则需要将其告知commit
,如果出现问题,则需要将其告知rollback
。因此,现在我们的代码中有很多斑点,如下所示:
OurConnectionClass conn = null;
try {
conn = OurConnectionClass(parameters);
// Do some stuff here...
conn.commit();
} catch (Throwable t) {
if (conn != null) {
conn.rollback();
}
throw t;
}
如果您忘记提交或回滚,则不会立即出现问题,但最终您会耗尽连接池,然后必须弄清楚哪里出了错。
我想找到一种方法,使OurConnectionClass
实现AutoClosable
,所以我可以这样做:
try (OurConnectionClass conn = new OurConnectionClass(parameters)) {
// Do some stuff here...
}
我觉得必须有一种方法可以执行此操作,但是我没有看到它。 AutoCloseable
仅调用close
方法,而没有传递任何参数。据我所知,没有办法知道是因为成功到达try块的末尾还是因为引发了异常而正在调用close。
答案 0 :(得分:3)
执行此代码段时。
try (OurConnectionClass conn = new OurConnectionClass(parameters)) {
// Do some stuff here...
conn.commit();
}
创建实例后,将始终调用 OurConnectionClass.close()
。因此,您只需添加一些逻辑即可检查是否已提交。例如。带有boolean
标志。这样,您就可以检查close()
方法是应该和平关闭连接还是应该回滚:
public class OurConnectionClass implements AutoCloseable{
private boolean committed; // initialized to false
public void commit(){
// commit
committed = true;
}
public void close() throws Exception{
if(!committed){
// rollback
}
}
}
答案 1 :(得分:1)
我认为您想要的语义是关闭交易回滚,除非使用OurConnectionClass的代码显式调用OurConnectionClass.commit()。
那么您就没有任何问题,因为您使用了close方法,那么只需测试是否有未完成的交易即可。如果有回滚,则记录错误。
答案 2 :(得分:0)
两者都做!
try (OurConnectionClass conn = new OurConnectionClass(parameters)) {
// Do some stuff here...
conn.commit();
} catch (Throwable t) {
conn.rollback();
throw t;
}
如果东西爆炸,closeable仍会自动关闭(在隐式finally
块中)。
顺便说一句,最好抛出一个域异常:
throw new MyStuffExploded(t);
因为重新抛出连接异常会使实现细节通过方法契约泄漏出去,而契约是一种耦合形式,这很不好。