4

我们已经编写了一个类,它打开了与服务器的连接。完成后,您需要告诉它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方法,不传递任何参数。据我所知,无法知道是否调用了 close 是因为成功到达 try 块的末尾还是抛出了异常。

4

3 回答 3

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
         }
    }
}
于 2018-07-26T14:35:25.547 回答
1

我认为您想要的语义是事务在关闭时回滚,除非使用 OurConnectionClass 显式调用 OurConnectionClass.commit() 的代码。

那么你没有任何问题,因为你的close方法,那么只需要测试是否有一个打开的事务。如果有回滚,并记录错误。

于 2018-07-26T14:36:05.433 回答
0

两者都做!

try (OurConnectionClass conn = new OurConnectionClass(parameters)) {
    // Do some stuff here...
    conn.commit();
} catch (Throwable t) {
    conn.rollback();
    throw t;
}

finally如果东西爆炸,可关闭对象仍会自动关闭(在隐式块中)。

顺便说一句,最好抛出一个域异常:

throw new MyStuffExploded(t);

因为重新抛出连接异常会让实现细节通过方法契约泄露出去,这是一种耦合形式,很糟糕。

于 2018-07-26T14:40:50.613 回答