0

I'm Java beginner, but I thought that when using try-catch-finally I don't have to declare the exception using throws SQLException. However if I don't use it the compiler gives me the error:

"unreported exception java.sql.SQLException; must be caught or declare to be thrown".

I included a catch so I'm not sure why this errors occurs.

public static ResultSet getResultSet ( String query ) 
{
    dbConn = getConnection();

    try
    {
       stmt = dbConn.createStatement( );

       ResultSet rs = stmt.executeQuery( query );

       return rs;
    }
   catch (SQLException ex)
   {
       return null;
   }
   finally
   {
       stmt.close();
       dbConn.close();
   }
}
aioobe
  • 413,195
  • 112
  • 811
  • 826
Mike55
  • 497
  • 13
  • 26
  • 5
    Help, a lot of kittens dies. You've declared `dbConn` and `stmt` as `static`. This code is definitely not threadsafe. I strongly recommend to redo the basic Java and JDBC tutorials. – BalusC Aug 11 '10 at 18:48
  • 1
    You are also going to get `SQLExceptions` when you use the `ResultSet`, so you might as well propagate the exception. The `ResultSet` probably isn't going to work after the connection is closed. You might want to consider the Execute Around idiom. http://stackoverflow.com/questions/341971/what-is-the-execute-around-idiom – Tom Hawtin - tackline Aug 11 '10 at 19:10
  • 1
    FWIW: the *normal* practice is to map the `ResultSet` to a `List` and return that instead. For some examples, [head here](http://stackoverflow.com/questions/3148092/java-jdbc-mysql-connector-how-to-resolve-disconnection-after-a-long-idle-time/3148857#3148857) and [here](http://stackoverflow.com/questions/1813858/sqlite-3-jdbc-driver-throws-resultsset-closed-exception-on-empty-resultset/1814443#1814443). – BalusC Aug 11 '10 at 19:14
  • 2
    Seriously, this is fine as an experiment for your own person learning, but don't put this on a live server or everything will break as soon as two people use it at the same time. :( – leoger Aug 11 '10 at 19:24

4 Answers4

9

It's because the close() methods:

stmt.close();
dbConn.close();

may throw SQLException and you haven't encapsulated them in a try/catch block.

A method may very well throw an exception from within a finally-clause, and, with no catch-clause handling those exceptions, the method must be declared to throw those exceptions.

Basically, you need to do something like

finally
{
    try {
        stmt.close();
    } catch (SQLException sqle) {
        // log the statement-close exception
    }

    try {
        dbConn.close();
    } catch (SQLException sqle) {
        // log the connection-close exception
    }
}
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • 2
    No, basically you need to put each `close()` in **its own** `try-catch` which is logging or ignoring the exception. In your example, if `stmt.close()` throws, then `dbConn.close()` will never take place. – BalusC Aug 11 '10 at 18:52
  • 2
    You may want to add nullchecks as well. – BalusC Aug 11 '10 at 19:12
4

Put dbConn = getConnection(); in the try section. It can throw an SQLException too.

Adam
  • 43,763
  • 16
  • 104
  • 144
  • That seems another homegrown static method. He might already have suppressed that exception inside the method (which is indeed a bad idea btw). – BalusC Aug 11 '10 at 18:54
2

Aside from the compiler errors, this code will fail at runtime.

When you close the Connection from which the ResultSet is created, the ResultSet will be invalidated, and any calls on it will fail. (Sure, some strange JDBC driver be implemented so that this could work, but this is incorrect usage of the JDBC API.)

The scope and lifetime of the ResultSet can't be any wider than its parent Connection and Statement.

erickson
  • 265,237
  • 58
  • 395
  • 493
0

The code you've written uses a class that has a type of exception that must be handled. You can do that in one of two ways, by passing it up the chain i.e. re-throwing the exception, or by actually handling it as some of the other comments show by putting the close methods in a try catch of there own in the finally block.

Typically you will see these in file IO classes where you should always close the object or stream to ensure you leave it in a valid state. Otherwise you are leaving it up to the Operating System to clean up for you.