Spring gives us some real cool advantages when integrating with databases. Theses advantages are applicable whether you connect to the database via JDBC or via frameworks.
Spring Data Exception mechanism:
When I first wrote my JDBC code in college, I came across the (in) famous SQLException. I added the catch block and then wondered what do do inside it. I mean if my db did not work, what graceful action was I to take ? My user could do zilch with an application where there was a query error or an unset db connection. The point was, SQLExceptions if any occurred and were handled during development. So what were these catch blocks doing in the code?
Also if there are some exceptions that can occur at run time and can be handled, it would mean that the code has to dig inside the SQLException to see if it can do anything. Hibernate developers had this in mind when they developed their framework. So they created their own exception hierarchy with different exceptions for different failure scenarios. So a user could actually deal with those exceptions that can be handled at run time and provide some graceful error handling to the user. But what of the other exceptions? How do we escape those empty catch blocks? The framework guys did the next cool thing. In Hibernate 3, they made the exceptions run time exceptions. It now meant "Handle if you can, else forget it." No more dumb catch blocks.
Spring has gone ahead and generalized this behaviour. So when working with Spring we have
I highlighted those that I found interesting.
Spring Data Exception mechanism:
When I first wrote my JDBC code in college, I came across the (in) famous SQLException. I added the catch block and then wondered what do do inside it. I mean if my db did not work, what graceful action was I to take ? My user could do zilch with an application where there was a query error or an unset db connection. The point was, SQLExceptions if any occurred and were handled during development. So what were these catch blocks doing in the code?
Also if there are some exceptions that can occur at run time and can be handled, it would mean that the code has to dig inside the SQLException to see if it can do anything. Hibernate developers had this in mind when they developed their framework. So they created their own exception hierarchy with different exceptions for different failure scenarios. So a user could actually deal with those exceptions that can be handled at run time and provide some graceful error handling to the user. But what of the other exceptions? How do we escape those empty catch blocks? The framework guys did the next cool thing. In Hibernate 3, they made the exceptions run time exceptions. It now meant "Handle if you can, else forget it." No more dumb catch blocks.
Spring has gone ahead and generalized this behaviour. So when working with Spring we have
- a hierarchy of data access exceptions
- each exception is descriptive and for a specific scenario
- all are run time and need to be only handled if they can be.
- they are not directly associated with a specific persistence framework and therefore can be used with JDBC/Hibernate/JDO/Ibatis or some other framework
Exception | Detail |
---|---|
DataAccessException | Root of the hierarchy of data access exceptions |
CannotAcquireLock Exception | Thrown on failure to acquire a lock during an update, for example during a "select for update" statement. |
CannotSerialize TransactionException | Thrown on failure to complete a transaction in serialized mode due to update conflicts. |
CleanupFailureData AccessException | Thrown when Spring couldn't cleanup after a data access operation, but the actual operation went OK. |
ConcurrencyFailure Exception | Thrown on concurrency failure. |
DataAccessResource FailureException | Thrown when a resource fails completely: for example, unable to connect to a database using JDBC. |
DataIntegrity ViolationException | Thrown when an attempt to insert or update data results in violation of an integrity constraint. |
DataRetrievalFailure Exception | Thrown if certain expected data could not be retrieved, e.g. when looking up specific data via a known identifier. This exception will be thrown either by O/R mapping tools or by DAO implementations. |
DeadlockLoserData AccessException | Generic exception thrown when the current process was a deadlock loser, and its transaction rolled back. |
DuplicateKeyException | thrown when an attempt to insert or update data results in violation of an primary key or unique constraint. |
EmptyResultData
AccessException
| thrown when a result was expected to have at least one row (or element) but zero rows (or elements) were actually returned. |
IncorrectResultSize DataAccessException | thrown when a result was not of the expected size, for example when expecting a single row but getting 0 or more than 1 rows. |
IncorrectUpdateSemantics DataAccessException | thrown when something unintended appears to have happened with an update, but the transaction hasn't already been rolled back. |
InvalidDataAccess ApiUsageException | thrown on incorrect usage of the API, such as failing to "compile" a query object that needed compilation before execution. |
InvalidDataAccess ResourceUsageException | thrown when we use a data access resource incorrectly. |
NonTransient DataAccessException | Root of the hierarchy of data access exceptions that are considered non-transient - where a retry of the same operation would fail unless the cause of the Exception is corrected. |
NonTransient DataAccess ResourceException | thrown when a resource fails completely and the failure is permanent. |
OptimisticLocking FailureException | thrown on an optimistic locking violation. |
PermissionDenied DataAccessException | thrown when the underlying resource denied a permission to access a specific element, such as a specific database table. |
PessimisticLocking FailureException | thrown on a pessimistic locking violation. |
RecoverableData AccessException | thrown when a previously failed operation might be able to succeed if the application performs some recovery steps and retries the entire transaction or in the case of a distributed transaction, the transaction branch. |
TransientData AccessException | Root of the hierarchy of data access exceptions that are considered transient - where a previously failed operation might be able to succeed when the operation is retried without any intervention by application-level functionality. |
TransientDataAccess ResourceException | thrown when a resource fails temporarily and the operation can be retried. |
TypeMismatch DataAccessException | thrown on mismatch between Java type and database type: for example on an attempt to set an object of the wrong type in an RDBMS column. |
UncategorizedData AccessException | Normal superclass when we can't distinguish anything more specific than "something went wrong with the underlying resource": for example, a SQLException from JDBC we can't pinpoint more precisely. |
No comments:
Post a Comment