【问题标题】:PreparedStatement resource leak while preparing a statement [duplicate]准备语句时 PreparedStatement 资源泄漏[重复]
【发布时间】:2016-11-10 00:30:54
【问题描述】:

我怀疑这可能是误报,但我不能确定,所以我有点困惑。我正在使用 Eclipse Neon,问题出现在我第三次准备声明时。我在下面做了几乎相同的事情,没有错误。

try{
        Connection con = MySQL.connection;
        PreparedStatement ps = con.prepareStatement("SELECT * from UsernameData "
                + "WHERE UUID = '" + player.getUniqueId() + "'");
        ResultSet rs = ps.executeQuery();
        if(rs.next() == true){
            ps = con.prepareStatement("update UsernameData set UUID = ?, Username = ? where UUID = ?");
            ps.setString(1, uuid);
            ps.setString(2, username);
            ps.setString(3, uuid);
            ps.execute();
            ps.close();
            rs.close();
            return;
        }
        ps = con.prepareStatement("insert into UsernameData(UUID, Username)"
                + " values (?, ?)");
        ps.setString(1, uuid);
        ps.setString(2, username);
        ps.execute();
        ps.close();
        rs.close();
        return;
    }catch(SQLException e){
        Bukkit.getServer().getLogger().warning("SQL Error: " + e);
    }

【问题讨论】:

    标签: java mysql prepared-statement resultset


    【解决方案1】:

    当您踩到 ps 进行插入时,您不会关闭第一组资源。

    您还应该考虑使用 try-with-resources:

        try (Connection con = MySQL.connection;
                PreparedStatement ps = con.prepareStatement("SELECT * from UsernameData "
                        + "WHERE UUID = '" + player.getUniqueId() + "'");
                PreparedStatement ps2 = con.prepareStatement("update UsernameData set UUID = ?, Username = ? where UUID = ?");
                PreparedStatement ps3 = con.prepareStatement("insert into UsernameData(UUID, Username)"
                        + " values (?, ?)");
                ResultSet rs = ps.executeQuery()) {
            if (rs.next() == true) {
                ps2.setString(1, uuid);
                ps2.setString(2, username);
                ps2.setString(3, uuid);
                ps2.execute();
                return;
            }
            ps3.setString(1, uuid);
            ps3.setString(2, username);
            ps3.execute();
            return;
        } catch (SQLException e) {
            Bukkit.getServer().getLogger().warning("SQL Error: " + e);
        }
    

    是的,第二个和第三个 PreparedStatement 可能会被浪费。如果您愿意,可以将它们包装在自己的 try-with-resources 中。

    但问题的症结在于你踩到了ps 变量。

    【讨论】:

    • 嗯,有道理,谢谢。
    • 不一定。我认为它不像任何类型的最佳实践或重用相同语句或 PreparedStatement 变量的问题。我将在此stackoverflow.com/questions/850878/…
    • 只需使用 ps.close() 关闭语句;很好。潜在的泄漏不是因为你在做 ps.execute();或 ps.close();当您无法关闭它们时。更重要的是连接,因为在您调用 connection.close 之前,数据库假定您的连接是打开的,即使您已通过将连接变量设置为 null 来取消引用它。
    • @Will Hartung 你的回答不是很准确
    猜你喜欢
    • 2014-04-01
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 2017-08-23
    • 2015-07-19
    • 2016-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多