实现AutoCloseable-如何知道try块中是否发生异常?

时间:2018-07-26 14:28:39

标签: java try-with-resources autocloseable

我们编写了一个类,用于打开与服务器的连接。完成操作后,如果一切成功,则需要将其告知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。

3 个答案:

答案 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);

因为重新抛出连接异常会使实现细节通过方法契约泄漏出去,而契约是一种耦合形式,这很不好。