简体   繁体   中英

Is it bad when a function returns without closing prepared statement / resultset?

So i stumbled upon a piece of java code, and noticed the login function returns 3 (int) if the user is banned. the closing of the resultset and the prepared statement used to login is after the return, so if the user is banned, it is never actually closed. My question is, if the function returns 3, does it reach the "finally" part where it closes everything?

I created a boolean and if the player is banned, the boolean is set to true. Then, at the end of the function where it returns "loginok" i added:

if(Banned)
    return 3;
else
    return loginok;

This should work but i was wondering if the previous method was bad or not.

The code looks somewhat like this:

    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;
    }

The previous method was ok. the finally clause will be executed. In case like that: The return statement is executed, finally block runs, the method actually returns.

Strongly recommend you refactor that code to use 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;
}

Now the question is a moot point, because they will always be closed.

You should use ARM with Java 7. That way, you don't have to worry about closing your resources in the finally block, but you do need to catch exceptions. There is a slight flaw in your code though. You should not be using a if block to iterate through the result set. You would only pick up the first row of the result set, not iterate through the rest.

Your code can be something like this

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 ...
       }
   }

}

You won't need to close any resources.

To your question:

if the function returns 3, does it reach the "finally" part where it closes everything?

Yes, it always reaches the finally block. That's what the finally block is for.

Also, you should remember to always free the resources you are allocating. As other answers point out, since Java 7 you can use the "try with resources", that it's easier to use, since the finally block is implicit.

Closing resources is specially critical in applications that run non-stop for a long time, such as web applications. Otherwise, you'll start losing resources pretty fast, and the server would need to be restarted very often.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM