Why is SQLException a checked exception

23,602

Solution 1

One reason would be that a method should throw exception which are consistent with the abstraction level of what the method does.

So a method which loads information from a database should not raise a SQLException, but rather a ResourceNotFoundException or a ResourceUnavailableException.

Making the SQLException checked is a way to force the developper to catch the Exception and wrap it in this new level of abstraction.

This argument is taken from Effective Java Second Edition by Joshua Bloch (Item 61: Throw exceptions appropriate to the abstraction).

Solution 2

There are a couple of approaches to the checked vs unchecked dilemma. Checking if the calling code can recover from the exception or not is one approach, this one however, I agree, does not explain why SQLExcption is a checked exception.

Another one, provided by Martin Fowler in his great book "Refactoring" suggests to verify wether it is the calling or the called method responsibility to make a check that might result in an exception.

If the caller method should perform a check prior calling the called method (e.g. making sure the arguments are not not null) then if this check has not been done it is clearly a programming error and then the called method should thrown an unchecked exception.

Now if it is the called method responsibility to make the check, because only this method can know how to perform such check then the exception thrown from the called method should be checked.

In case of SQLException I think only this class can know:

  • there is a syntax error in the query as this depends on the database
  • the connection has died
  • there is a permission problem

Solution 3

Catching exceptions grant us the ability to recover from exceptional conditions, true, but they also allow us to do other things.

You cannot recover from a SQLException in that there isn't much you can do to fix the problem at run time, but there are some useful things you can do:

  • Log the exception for debugging information
  • Rollback a transaction

You could always log the exception at a higher level (or lower, depending on perspective), but you lose some semantic value, both at debugging time and when reviewing the code.

If you do something like:

try { ... }
catch(SQLException e) 
{ 
    SomeLogger.log(...);
    rollback();
    throw e;
}

and come back to this code later, you'll instantly realize that the code in the try can fail without having to mentally parse the code to determine if it can fail.

Another thing you could do is ensure any database resources have been released, though I'm not sure if this can happen off hand.

Share:
23,602
Bohemian
Author by

Bohemian

Self-proclaimed SQL guru, Java pro and regex fan... and currently elected moderator. In all code, I strive for brevity (without loss of legibility). The less code there is, the less places there are for bugs to lurk. While contributing here, I have learned that say not that you know something until you try to teach it. My real name is Glen Edmonds. If one of my posts "changed your life", you can donate to my Liberapay account. FYI, that cute animal I use for my avatar is a wombat.

Updated on July 09, 2022

Comments

  • Bohemian
    Bohemian almost 2 years

    Can anyone think of a rational reason why SQLException is a checked exception?

    Yes, there could be a syntax error in the query
    Yes, the connection might have died
    Yes, there might be a permission problem
    Etc, etc blah blah blah

    But practically 100% of the time (once you're running in production), there isn't any problem.

    If there is a problem, the calling code can't do anything to recover, so for that reason it should be unchecked.

    Being checked create masses of perfunctory try catch blocks throughout the code, as anyone who has been involved with a project that uses JDBC will attest. The code clutter is significant.

    Because of the esoteric nature of SQL, the myriad of reasons you may get an SQLException and their complexity means you basically can not recover, unless the exception is caused by temporary network problem, but even then in a synchronous call, you're sunk anyway because you can't wait indefinitely for the network problem to be resolved, so you're going to have to fail the transaction.

    Typically, calling SQL looks like this:

    try {
        // make some SQL call(s)
    } catch {SQLException e) { 
        // log the exception
        return; // and give up
    }
    

    Such code adds no value. There nothing reasonable you can do to recover. You might as well let a runtime exception bubble up - ie SQLException should be a runtime (unchecked) exception.

  • Bohemian
    Bohemian about 11 years
    But why would "loading data from the database" fail? The fact is, it doesn't fail! It might "fail" in the sence that a row wasn't found, but that won't throw an SQLException. And if it does fail, it "explodes" and the caller can't do anything to recover - that's the essence of why to use an unchecked exception.
  • Bohemian
    Bohemian about 11 years
    OK. Let's suppose to check that the SQL syntax is correct (by re-writing the SQL parser in java!), and say there is an error - what are you going to do about it? Nothing! You can't fix it, so why are you catching an exception? The only action you are going to do is log the exception and throw another exception - why not just let an unchecked exception percolate up?
  • Adam Siemion
    Adam Siemion about 11 years
    Ok, I agree, in most cases your application will not be able to recover in such case. But in case of "the connection has died" it can easily recover from it by re-establishing a connection to the database. I guess, the way you perceive if an exception is recoverable or not depends solely on the author of the calling method, which means it cannot be used as a criteria for deciding between a checked vs unchecked exception.
  • obourgain
    obourgain about 11 years
    I agree in most cases there is nothing to do except "explode" the application. But I can imagine some cases where you should not. For example if there exist a backup database, or the information you cannot fetch is not in the primary database (e.g. error when fetching your wishlist on an ecommerce site).
  • Bohemian
    Bohemian about 11 years
    Note that "information is not the the primary database" won't throw an exception - you'll just get an empty rowset. You're talking about the primary database having gone down - pretty catastrophic. I you've got code to deal with that, there's nothing stopping you from catching an unchecked SQLException and doing something. What if folks don't have that capability - they would like SQLException to be a runtime.
  • blacelle
    blacelle about 10 years
    The question is not about the relevancy of catching the exception (as RuntimeException can be caught), but about the relevancy of forcing to catch it (as adding throw SQLException in the method signature is probably not relevant either and according to the question, in most cases, nothing is done except rethrowing)
  • Usman Mutawakil
    Usman Mutawakil almost 4 years
    The ResourceNotFoundException is a fair one but I would argue if you're building this type of library or SDK around JDBC you would want to wrap lots of lower level methods in generic Try/Catch/Exception blocks anyway, for any possible error but you'd still want the underlying SQLExeption and its cause to be made known. Its not like you'll change the SQLException into a ResourceNotFound without mentioning SQL syntax is wrong, connection pool closed, etc etc.