tags:

views:

175

answers:

4

I am using JDBC to retrieve data from a database. I understand that a Statement needs to be closed after it is used. However, I keep run into the same error telling me that no operation is allowed after the statement is closed. The structure of my code is like

public void foo() {

Statement;
try {
} catch{
}
Statement.close();
}

In my code, I need to call this function repeatedly. I was wondering where to close the Statement.

Thanks

+4  A: 

According to the Javadocs Statement.close() Releases this Statement object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed. It is generally good practice to release resources as soon as you are finished with them to avoid tying up database resources. Which means you should close it after you done and not planning to use it again. I would, actually pay more attention to closing your Connection.

In your method which you say you call repeatedly you are calling Statement.close() which means that you can only use it once since after the first call you Statement is closed and cannot be used anymore.

It would be nice to see some of your code if you want a better answer

DroidIn.net
Same. in my practice, just place the close() at the very end of code, where no more extra lines are needed to executed.
Shivan Raptor
+1  A: 

Note that JDBC resources should always be closed, so, its better to put that to the 'finally' block.

You can also consider Spring DAO usage - it is a thin wrapper on top of JDBC and covers most of JDBC boilerplate stuff.

denis.zhdanov
A: 
  1. ResultSets also need to be closed.

  2. It sounds like you might be doing something like accessing a Blob, the Blob object often goes back through the connection to read the byte data from the database. So read all of the byte[] data before you close the connection. If that's not possible because there's too much data and you are trying to stream the bytes then you're just going to have to stick the connection somewhere safe and call close on it later.

  3. Close statements should go into finally blocks, and be null protected - but it's such common and ugly code so stick in a static method somewhere.


public List someMethod() {

 Statement stmt;
 ResultSet rset;
 try {
  stmt = con.createStatement();
  rset = stmt.executeQuery(....);

  List resultList = ...create a list
  // get the data from the rset

  return resultList;
 }
 catch(SQLException ex) {
  throw new MyDatabaseException(ex);
 }
 finally {
 }

}

public class DatabaseUtils {

 public void close(Statement stmt, ResultSet rset) {
  try {
    if(rset != null) {
      rset.close();
    }
  }
  catch(SQLException ex) {
    throw new MyDatabaseException(ex);
  }
  finally {
    if(stmt != null) {
      throw new MyDatabaseException(ex);
    }
  }
 }

}

Richard Perfect
That code doesn’t even compile—and it wouldn’t make much sense if it did.
Bombe
Yeah - partially I was in a hurry and also I was having problems getting the code to format for some reason, I just gave up and went with something that had the main ideas. Though I see I missed the call to the DatabaseUtils.close() method in the finally block. The people below got the idea :-)
Richard Perfect
A: 

Isn't this quite the normal way of doing this:

Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;

try {

// do your database stuff here

} catch(SQLException e) {

// do your proper error handling here

} finally {

   try {
      if ( resultSet!=null ) resultSet.close();
   } catch (Exception e ) {
      // empty catch block, there's isn't much you can do if closing fails
   }

   try {
       if ( statement!=null ) statement.close();
   } catch (Exception e ) {
      // empty catch block, there's isn't much you can do if closing fails
   }

   try {
       if ( connection!=null )  connection.close();
   } catch (Exception e ) {
      // empty catch block, there's isn't much you can do if closing fails
   }
}
MarkoU
There are a number of problems with that code: Unnecessary use of `null`s makes it unclear (use `acquire(); try { use(); } finally { release(); }`. An exception from closing the `ResultSet` will leave the `Connection` open (the statement adds more). You've allowed normal exit in the case of an exception having been thrown.
Tom Hawtin - tackline
it is not good. What will happen if closing of resultSet fails?!? statement and connection would be left unclosed...
ante.sabo
I stand corrected. What if we put each close in its own try-catch within the finally block? The finally block gets a bit long and could be refactored into a separate utility method, but this describes the idea.
MarkoU