Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 实现自动关闭-如何知道try块中是否发生异常?_Java_Try With Resources_Autocloseable - Fatal编程技术网

Java 实现自动关闭-如何知道try块中是否发生异常?

Java 实现自动关闭-如何知道try块中是否发生异常?,java,try-with-resources,autocloseable,Java,Try With Resources,Autocloseable,我们编写了一个类,它打开了与服务器的连接。完成后,如果一切都成功,您需要告诉它执行commit,如果出现问题,您需要告诉它执行rollback。所以现在我们的代码中有很多点是这样的: OurConnectionClass conn = null; try { conn = OurConnectionClass(parameters); // Do some stuff here... conn.commit(); } catch (Throwable t) { i

我们编写了一个类,它打开了与服务器的连接。完成后,如果一切都成功,您需要告诉它执行
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;
}
如果忘记提交或回滚,则不会立即出现问题,但最终会耗尽连接池,然后必须找出错误所在

我想找到一种方法,使我们的ConnectionClass实现自动关闭,这样我就可以做如下设置:

try (OurConnectionClass conn = new OurConnectionClass(parameters)) {
    // Do some stuff here...
}

我觉得一定有办法做到这一点,但我没有看到
AutoCloseable
只调用
close
方法,不向其传递任何参数。就我所见,无法知道调用close是因为成功到达了try块的末尾,还是因为抛出了异常。

执行此代码段时

try (OurConnectionClass conn = new OurConnectionClass(parameters)) {
    // Do some stuff here...
    conn.commit();
}
OurConnectionClass.close()
将始终在创建实例后调用。因此,您可以添加一些逻辑来检查是否进行了提交。例如,使用
布尔
标志。这样,您就可以在
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
         }
    }
}

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

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

两者都要做

try (OurConnectionClass conn = new OurConnectionClass(parameters)) {
    // Do some stuff here...
    conn.commit();
} catch (Throwable t) {
    conn.rollback();
    throw t;
}
如果东西爆炸,可关闭项仍然自动关闭(在隐式
finally
块中)

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

throw new MyStuffExploded(t);

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

现在我已经把这些都写出来了,我想知道我是否应该使用匿名函数而不是尝试使用
try with resources
?我可以让
OurConnectionClass
接收并尝试运行它,如果成功,它会在之后运行
commit()
,如果失败,它会在。。。我可以让它成为一个不返回任何内容的静态方法,而不是返回一个实例。听起来可能比我想象的要复杂一些。。。在尝试之前,我会先看看其他人对此有何想法……使用
AutoClosable
您的意思是
AutoClosable
?您能指定您所指的接口吗?请注意,如果构造函数失败并引发异常,则不会调用close()。根据,您可以在处理异常的try-with-resource块之后定义一个
catch
-块。@Leviand-我从上下文中思考(事实上我说的是Java的try-with-resource)很明显,我指的是标准Java库中的
AutoCloseable
接口,而不是第三方的接口。无论如何,你是对的,我在几个地方把这个名字拼错了。我已经修复了它。可能想让
提交
易失性
@Bohemian:为什么?@Bohemian我不是很确定,但是
try with resources
-中的逻辑最终是在不同的线程中执行的吗?。因为在
twr
块中不应该有多个线程访问
conn
,如果我正确理解了这个问题是的。。。这听起来确实比我们现在所做的有所改进,但我担心当开发人员忘记提交并且不知道发生了什么时会浪费时间。我可以让close调用而不提交两个调用回滚并抛出一个异常。我从未见过在没有发生异常的情况下使用回滚。我想我将深入研究使用lambdas来实现这一点,但是…是否应该只使用
可丢弃的t
,或者更确切地说,根据它的重要性重新使用?