【问题标题】:Java SQL .close() necesary if keep re-instantiating object?如果继续重新实例化对象,Java SQL .close() 是否必要?
【发布时间】:2021-11-01 09:12:53
【问题描述】:

我知道,如果您创建 SQL PreparedStatement 或 ResultSet,您应该在完成后对资源使用 .close()。但是,如果我正在循环并只是在每次迭代中重新创建 PreparedStatement,我是否仍然需要在每次迭代期间调用 .close() ,或者仅在我完成时调用它?

例如,如果我有这个:

private Connection con;
private String[] queries;
private PreparedStatement stmt;

...
create connection
fill array queries with 10 queries in it
...

for (int i = 0; i < 10; i++) {

    stmt = con.prepareStatement(queries[i], Statement.RETURN_GENERATED_KEYS);
    stmt.executeUpdate();
    
    // necessary?
    stmt.close()
}

每次迭代都需要 .close() stmt,还是应该在循环完成时才这样做?为什么或者为什么不?谢谢。

【问题讨论】:

  • 这能回答你的问题吗? Close result set in loop using Java
  • 您不是“在每次迭代中重新创建 PreparedStatement”,您正在创建一个新的不同的 PreparedStatement 对象并扔掉previous PreparedStatement 对象!

标签: java jdbc prepared-statement


【解决方案1】:

每次迭代都会创建一个新对象。您打开的每条语句都可以使数据库服务器上的资源保持打开的时间超过必要的时间。关闭连接应该会清理所有内容,但众所周知,JDBC 驱动程序存在无法清理的错误。

在 finally 块中将它们全部关闭,或者对资源使用 try。

【讨论】:

    【解决方案2】:

    对象超出范围后仍然存在

    当您将引用变量重新分配给另一个对象时,之前引用的对象仍然存在于内存中。他们的close 方法没有被调用。

    如果没有在其他地方引用,孤立对象将成为垃圾回收的候选对象。但是垃圾回收不会调用对象的close方法。

    尝试资源

    您应该学习使用 try-with-resources 语法来自动关闭资源,例如 JDBC 对象、文件 I/O 对象等。请参阅 Oracle 的 tutorial。尽快关闭这些资源,一旦你用完它们。

    示例代码

    您的代码应类似于以下示例代码。请注意每个 JDBC 对象在我们使用完毕后是如何立即关闭的:ConnectionPreparedStatementResultSet

    DataSource 对象不会关闭,因为它实际上并未“打开”。 DataSource 对象仅包含连接数据库所需的信息(服务器地址、用户名、密码等)。

    String[] queries = new String[ 10 ];
    // … populate queries array.
    
    DataSource dataSource = this.fetchDataSource();
    try (
            Connection conn = dataSource.getConnection() ;
    )
    {
        for ( int i = 0 ; i < 10 ; i++ )
        {
            try (
                    PreparedStatement ps = conn.prepareStatement( queries[ i ] , Statement.RETURN_GENERATED_KEYS ) ;
            )
            {
                ps.setObject( 1 , LocalDate.of( 2021 , Month.JANUARY , 23 ) );
                int countOfRowsAffected = ps.executeUpdate();
                if ( countOfRowsAffected > 0 )
                {
                    try ( ResultSet rs = ps.getGeneratedKeys() ; )
                    {
                        while ( rs.next() )
                        {
                            // … process your keys.
                        }
                    }
                    // The `ResultSet` object is auto-closed by this point.
                }
            }
            // The `PreparedStatement` object is auto-closed by this point.
        }
    } catch ( SQLFeatureNotSupportedException e )
    {
        e.printStackTrace();
    } catch ( SQLTimeoutException e )
    {
        e.printStackTrace();
    } catch ( SQLException e )
    {
        e.printStackTrace();
    }
    // The `Connection` object is auto-closed by this point.
    

    使用 try-with-resources 的另一个好处是您的意图非常明确。任何阅读您的代码的人都知道您打算在哪里关闭每个资源。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-14
      • 1970-01-01
      • 1970-01-01
      • 2022-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多