java, how to close a statement that is used in different methods?

advertisements

I have two static methods in two classes: Account and FunnyDB. in FunnyDB I have a method which is used in Account to retrieve object from database. I am wondering if it is possible to somehow close statement (stmt) in the FunnyDB from Account method. Also, if it is not really possible, what are the consequences of leaving statement not closed? These are my methods:

FunnyDB:

/**
 * Returns ResultSet from query to get data to create object. Identufy data by id
 *
 * @param tableName Name of he table to search. Use getClass().getSimpleName().
 * @param id
 * @return
 */
public static ResultSet getObjectResultSetById(String tableName, int id) {
    ResultSet rs = null;
    try {
        // gets object's details from database
        Statement stmt = con.createStatement(); //<-- I WANT TO CLOSE THIS PARAMETER
        String sql = "SELECT * \n"
                + "FROM " + tableName + " \n"
                + "WHERE " + tableName.toLowerCase() + "_id = " + id;
        rs = stmt.executeQuery(sql);
        //TODO: Closing rs and stmt? .close().
    } catch (SQLException ex) {
        Logger.getLogger(FunnyDB.class.getName()).log(Level.SEVERE, null, ex);
        System.out.println(ex.getMessage());
    }
    return rs;
}

Account:

/**
 * Returns object found by given ID.
 *
 * @param id Object ID.
 * @return Object from database.
 */
public static Account getAccountFromDatabaseById(int id) {
    Account account = null;
    try {
        ResultSet rs = FunnyDB.getObjectResultSetById("Account", id);
        // create object to return
        while (rs.next()) {
            account = new Account(rs.getInt("account_id"), rs.getString("account_name"), rs.getString("account_type"), Currency.getCurrencyFromDatabaseById(rs.getInt("currency_id")), rs.getDouble("start_amount"), rs.getDouble("balance"));
        }
        rs.close();
//close stmt?????
    } catch (SQLException ex) {
        Logger.getLogger(Currency.class.getName()).log(Level.SEVERE, null, ex);
        System.out.println(ex.getMessage());
    }
    return account;
}

Thank you for help


Making a class responsible for closing a Statement that is different than the one that created it is a bad idea. What if the calling code forgets to close it?

The FunnyDB class should be responsible for closing the Statement; it created it. To do this, it must read the ResultSet itself, creating the Account, so that it's completely done with the ResultSet. This way, there is no problem closing the ResultSet and the Statement before it returns.

Move the code that creates the Account with calls to the ResultSet into FunnyDB's getObjectResultSetById method. Have that method return the Account instead of the ResultSet. Close the ResultSet and Statement there. You might want to rename it getAccountById. You may also want to use a "try with resources" statement if you're using Java 7+. You can have the ResultSet and Statement closed automatically. If you are stuck with Java 6 or below, use a finally block to close them, to ensure that everything is closed before returning.

The getAccountFromDatabaseById in Account doesn't need to manipulate the ResultSet at all; it just needs to use the Account returned by FunnyDB.