PreparedStatement 中的 Java 资源泄漏

Posted

技术标签:

【中文标题】PreparedStatement 中的 Java 资源泄漏【英文标题】:Java resource leak in PreparedStatement 【发布时间】:2014-10-17 08:22:45 【问题描述】:

我正在用 Java 编写涉及数据库 (SQLite) 的代码,而且我是新手,所以我需要这方面的帮助。 我的代码如下所示:

Connection connection = null;
try 
    connection = SQLiteConnector.getConnection(database Name);
    PreparedStatement prepStat = connection.prepareStatement("some SQL stuff"); 
    ResultSet result= prepStat.executeQuery();
    // Use of result

    if (condition1)

        prepStat = connection.prepareStatement("some SQL stuff");
        result = prepStat.executeQuery();
        // Another use of result

        if (condition2)
            prepStat = connection.prepareStatement("some SQL stuff");
        
        else
            prepStat = connection.prepareStatement("some SQL stuff");
        

        result = prepStat.executeQuery();
        // Use of result

        result.close();
        prepStat.close();
    
 catch (Exception e) 
    // Exception management

finally
    SQLiteConnector.closeConnection(connection);

我在 else 块中收到异常消息:“资源泄漏:'stat' 未在此位置关闭”。我应该如何重构它?

提前谢谢你

【问题讨论】:

发布堆栈跟踪并指向抛出它的行。还是编译时错误? 资源泄漏消息只是一个警告 - 如果您不解决该问题,您的代码仍将编译和运行。假设您的意思是prepStat 而不是stat,警告是否显示在prepStat.close(); 行或附近?另外,您使用的是哪个版本的 JDK? 你好像不是.close()“第一”prepStat,是吗? 看看这个***.com/questions/22096398/…,你必须关闭preparedStatement才能重用它。 另外,如果你使用 Java 7+,PreparedStatement 实现 AutoCloseable 所以你可能想要使用 try-with-resources 块 【参考方案1】:

PreparedStatements 应始终在 JDBC 中显式关闭。使用 PreparedStatement 的一般模式是:

创建语句。 设置参数并执行。 设置不同的参数并执行。 设置更多参数并执行。 关闭语句。

从 Java 7 开始,确保始终正确执行此操作的最简单方法是在 try with resources 块中使用语句。

【讨论】:

【参考方案2】:

使用单独的变量,绝对是 try-with-resources。

    try (PreparedStatement prepStat =
            connection.prepareStatement("some SQL stuff");
            ResultSet result = prepStat.executeQuery()) 
        ...
        try (PreparedStatement prepStat2 =
                connection.prepareStatement(condition2 ? "some SQL stuff" : "some SQL stuff") 
            try (ResultSet result2 = prepStat.executeQuery();
                // Use of result2
            
        
    

然后一切都很好地结束了,即使有异常或返回语句。

【讨论】:

【参考方案3】:

您在重新使用之前没有关闭 prepStat。还要尝试关闭 finally 块中的语句而不是尝试,因为它可能会使可关闭的语句保持未关闭状态。

if (condition1)

    prepStat = connection.prepareStatement("some SQL stuff");
    result = prepStat.executeQuery();
    // Another use of result

    prepStat.close(); //close the statement 

    if (condition2)
        prepStat = connection.prepareStatement("some SQL stuff");
    
    else
        prepStat = connection.prepareStatement("some SQL stuff");
    

    result = prepStat.executeQuery();
    // Use of result

    result.close();
    prepStat.close();

【讨论】:

以上是关于PreparedStatement 中的 Java 资源泄漏的主要内容,如果未能解决你的问题,请参考以下文章

PreparedStatement 中的 Java 资源泄漏

PreparedStatement 不适用于 Java 中的 Sybase IQ

Java -- JDBC 学习--PreparedStatement

尝试插入文件时java中的preparedStatement SQL错误[关闭]

Java中的JDBC

JDBC mysql不支持PreparedStatement中的LIMIT占位符?