The theory for checked exceptions is simple.
When designing an interface, think of exceptional cases that can occur, and will occur, with the normal state of a method call. Declare these exceptions in your interface, as the programmer will have to handle them directly.
For example, a bank account withdraw method may declare an OverdraftException, which is an expected exception - a withdrawal may fail due to overdraft, but this type of failure may be handled differently by the client code (one may decide to completely deny the withdrawal, another may decide to apply a huge penalty and allow for a negative balance to be recorded, another may decide that their client is allowed to draw from a different account).
However, runtime exceptions were supposed to be programming errors that weren't supposed to be handled directly - such as NullPointerExceptions, which only occur if methods take invalid arguments or don't check for such cases directly.
This is a good theory. However, Java messed up with its implementation of Exceptions, and this threw the book of this theory out the window.
There are two cases that I will illustrate where Java messed up with its implementation of Exceptions. These are IOException and SQLException.
An IOException occurs anytime, anywhere a stream in the IO libraries of Java messes up. This is a checked exception, however. But, generally you cannot do anything but log that an error occur - if you're simply writing to the console, what can you reasonably be expected to do if you suddenly get an IOException when you're writing to it?
But there's more.
IOException also hides stuff like file exceptions and network exceptions. They may be subclasses of IOException floating around for that, but it is still a checked exception. If your writing to an external file fails, you can't really do much about it - if your network connection is severed, ditto.
SQLException is the same way. Exception names should show what happened when they are called. SQLException does not. SQLException is thrown any single time any possible number of errors are encountered when dealing with a database - MOST OF WHICH THAT HAVE NOTHING TO DO WITH SQL.
Therefore, programmers typically get annoyed with handling exceptions, and let Eclipse (or whatever IDE they're using) generate blocks like this:
try {
thisMethodThrowsACheckedExceptionButIDontCare();
}
catch(Exception e) {
e.printStackTrace();
}
However, with RuntimeExceptions, these intentionally bubble up and eventually get handled by the JVM or container level. This is a good thing - it forces errors to show up and then you must fix the code directly instead of ignoring the exception - you may still end up just printing the stack trace (hopefully logging it instead of printing to the console directly), but then there will be an exception handler that you were forced to write because of a real problem - not because a method said that it might possibly throw an Exception, but that it did.
Spring uses a DataAccessException to wrap SQLExceptions so that you don't have to handle them as a checked exception. It makes code much cleaner as a result - if you expect a DataAccessException, you can handle it - but most of the time you let it propagate and be logged as an error, because your SQL should be debugged by the time you release your application, meaning the DataAccessException is probably a hardware issue that you could not resolve - DataAccessException is a much more meaningful name than SQLException, because it shows that access to data failed - not that your SQL query was nessecarily at fault.