当函数不关闭准备好的语句/结果集而返回时,是否很糟糕?

时间:2019-04-27 19:58:48

标签: java sql

因此,我偶然发现了一段Java代码,并注意到如果用户被禁止,则登录功能返回3(int)。结果集和用于登录的准备好的语句的关闭是在返回之后进行的,因此,如果禁止了该用户,则它实际上永远不会关闭。 我的问题是,如果函数返回3,它会到达“最终”部分并关闭所有内容吗?

我创建了一个布尔值,如果播放器被禁止,则布尔值设置为true。然后,在函数返回“ loginok”的末尾,我添加了:

if(Banned)
    return 3;
else
    return loginok;

这应该可行,但是我想知道以前的方法是否正确。

代码看起来像这样:

    public int login(String login, String pwd) {

        Connection con = DatabaseConnection.getConnection();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = con.prepareStatement("SELECT id, password, banned WHERE name = ?");
            ps.setString(1, login);
            rs = ps.executeQuery();
            if (rs.next()) {
                int banned = rs.getInt("banned");
                if (rs.getByte("banned") == 1) { 
                    return 3;
                }
                accId = rs.getInt("id");
                String passhash = rs.getString("password");
                ps.close();
                rs.close();
                if (getLoginState() > LOGIN_NOTLOGGEDIN) {
                    loggedIn = false;
                    loginok = 7;
                } else if (pwd.equals(passhash)) {
                    loginok = 0;
                } else {
                    loggedIn = false;
                    loginok = 4;
                }
            }
        } catch (SQLException e) {
            log.error("ERROR", e);
        } finally { //Or maybe its fine because of this?
            try {
                if (ps != null && !ps.isClosed()) {
                    ps.close();
                }
                if (rs != null && !rs.isClosed()) {
                    rs.close();
                }
            } catch (SQLException e) {
            }
        }
        return loginok;
    }

4 个答案:

答案 0 :(得分:2)

以前的方法还可以。 return子句将被执行。 在这种情况下:执行finally语句,运行{{1}}块,该方法实际上返回。

答案 1 :(得分:1)

强烈建议您重构该代码以使用try-with-resources。

public int login(String login, String pwd) {
    Connection con = DatabaseConnection.getConnection();
    try (PreparedStatement ps = con.prepareStatement("SELECT id, password, banned WHERE name = ?")) {
        ps.setString(1, login);
        try (ResultSet rs = ps.executeQuery()) {
            if (rs.next()) {
                if (rs.getByte("banned") == 1) { 
                    return 3;
                }
                accId = rs.getInt("id");
                String passhash = rs.getString("password");
                if (getLoginState() > LOGIN_NOTLOGGEDIN) {
                    loggedIn = false;
                    loginok = 7;
                } else if (pwd.equals(passhash)) {
                    loginok = 0;
                } else {
                    loggedIn = false;
                    loginok = 4;
                }
            }
        }
    } catch (SQLException e) {
        log.error("ERROR", e);
    }
    return loginok;
}

现在的问题是有争议的,因为它们将始终封闭。

答案 2 :(得分:0)

您应该将ARM与Java 7一起使用。这样,您不必担心在finally块中关闭资源,但是您确实需要捕获异常。但是,您的代码中有一个小缺陷。您不应该使用if块来遍历结果集。您只会选择结果集的第一行,而不会遍历其余部分。

您的代码可以是这样的

try(Connection con = DatabaseConnection.getConnection();
    ps = con.prepareStatement("SELECT id, password, banned WHERE name = ?");) {
   ps.setString(1, login);
   try(ResultSet rs = ps.executeQuery();) {
       while (rs.next()) {
            ... You calculations here ...
       }
   }

}

您不需要关闭任何资源。

答案 3 :(得分:0)

对您的问题:

  

如果函数返回3,它会到达“最终”部分并关闭所有内容吗?

是的,它总是到达finally块。这就是finally块的用途。

此外,您应该记住始终释放要分配的资源。正如其他答案所指出的那样,由于Java 7可以使用“尝试资源”,因此,由于finally块是隐式的,因此更易于使用。

在长时间不间断运行的应用程序(例如Web应用程序)中,关闭资源特别重要。否则,您将开始非常快地失去资源,并且服务器将需要非常频繁地重新启动。