Try-with-resources - 它会自动关闭连接吗? Java

Try-with-resources - Does it automatically close the connection? Java

我一直在研究 SQL 实用程序,我正在尝试在多个函数的预准备语句中设置参数。

为了减少代码,我有一个函数 returns 一个准备好的语句,其中设置了所有参数。

我的问题是:
configureStatement() 中的连接引用是否使用 query() 中的资源尝试关闭?如果不是,如何重构代码以每次都关闭 PreparedStatementConnection

    public void query(String queryString, List<String> queryParams, Consumer<ResultSet> sqlConsumer)
    {
        try (PreparedStatement preparedStatement = this.configureStatement(queryString, queryParams))
        {
            sqlConsumer.accept(preparedStatement.executeQuery());
        } catch(SQLException exception)
        {
            exception.printStackTrace();
        }
    }
    
    private PreparedStatement configureStatement(String query, List<String> queryParams) throws SQLException
    {
        PreparedStatement preparedStatement = this.getConnection().prepareStatement(query);
        for (int i = 0; i < queryParams.size(); ++i)
            preparedStatement.setString(i, queryParams.get(i));

        return preparedStatement;
    }

问:是什么让您认为从您自己的方法之一返回对象不会允许对象在 Java 尝试使用资源时“关闭”?

来自 Java 文档:

https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.

关键问题:从您的方法返回的对象必须实现 java.lang.AutoCloseable。在你的情况下,它确实:

https://docs.oracle.com/javase/8/docs/api/java/sql/PreparedStatement.html

Interface PreparedStatement

  • All Superinterfaces:

    AutoCloseable, Statement, Wrapper

不,try with resources 不会关闭在 PreparedStatement 中使用的 Connection。 仅 PreparedStatement 及其 ResultSet 已关闭。

When a Statement object is closed, its current ResultSet object, if one exists, is also closed.

可以重复使用一个 connection 来执行多个 PreparedStatements。每个都在使用后关闭。当不再需要 connection 时,也可以将其关闭。

你或许可以这样检查:

public void query(String queryString, List<String> queryParams, Consumer<ResultSet> sqlConsumer)
{
    Connection connection;
    try (PreparedStatement preparedStatement = this.configureStatement(queryString, queryParams))
    {
        connection=preparedStatement.getConnection();
        sqlConsumer.accept(preparedStatement.executeQuery());
    } catch(SQLException exception)
    {
        exception.printStackTrace();
    }
    if(connection!=null){
        System.out.println("Is Connection closed:"+connection.isClosed());
    }
}

private PreparedStatement configureStatement(String query, List<String> queryParams) throws SQLException
{
    PreparedStatement preparedStatement = this.getConnection().prepareStatement(query);
    for (int i = 0; i < queryParams.size(); ++i)
        preparedStatement.setString(i, queryParams.get(i));

    return preparedStatement;
}

通过将 try-with-resources 与多个语句一起使用来关闭连接的重构:

public void query(String queryString, List<String> queryParams, Consumer<ResultSet> sqlConsumer)
    {

        try ( Connection connection=this.getConnection(); 
              PreparedStatement preparedStatement = this.configureStatement(connection, queryString, queryParams);)
        {
            sqlConsumer.accept(preparedStatement.executeQuery());
        } catch(SQLException exception)
        {
            exception.printStackTrace();
        }
        if(connection!=null){
           connection.close();
        }
    }

private PreparedStatement configureStatement( Connection connection,String query, List<String> queryParams) throws SQLException
    {
        PreparedStatement preparedStatement = connection.prepareStatement(query);
        for (int i = 0; i < queryParams.size(); ++i)
            preparedStatement.setString(i, queryParams.get(i));

        return preparedStatement;
    }