Try-with-resources - 它会自动关闭连接吗? Java
Try-with-resources - Does it automatically close the connection? Java
我一直在研究 SQL 实用程序,我正在尝试在多个函数的预准备语句中设置参数。
为了减少代码,我有一个函数 returns 一个准备好的语句,其中设置了所有参数。
我的问题是:
configureStatement()
中的连接引用是否使用 query()
中的资源尝试关闭?如果不是,如何重构代码以每次都关闭 PreparedStatement
和 Connection
?
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;
}
我一直在研究 SQL 实用程序,我正在尝试在多个函数的预准备语句中设置参数。
为了减少代码,我有一个函数 returns 一个准备好的语句,其中设置了所有参数。
我的问题是:
configureStatement()
中的连接引用是否使用 query()
中的资源尝试关闭?如果不是,如何重构代码以每次都关闭 PreparedStatement
和 Connection
?
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;
}