30 diciembre 2009

Hibernate exceptions

Any Hibernate operation, including flushing the persistence context, can throw a
RuntimeException. Even rolling back a transaction can throw an exception! You
want to catch this exception and log it; otherwise, the original exception that led
to the rollback is swallowed.
An optional method call in the example is setTimeout(), which takes the
number of seconds a transaction is allowed to run. However, real monitored trans-
actions aren’t available in a Java SE environment. The best Hibernate can do if
you run this code outside of an application server (that is, without a transaction
manager) is to set the number of seconds the driver will wait for a Prepared-
Statement to execute (Hibernate exclusively uses prepared statements). If the
limit is exceeded, an SQLException is thrown.

You don’t want to use this example as a template in your own application,
because you should hide the exception handling with generic infrastructure code.
You can, for example, write a single error handler for RuntimeException that
knows when and how to roll back a transaction. The same can be said about open-
ing and closing a Session. We discuss this with more realistic examples later in
the next chapter and again in chapter 16, section 16.1.3, “The Open Session in
View pattern.”
Hibernate throws typed exceptions, all subtypes of RuntimeException that help
you identify errors:
■ The most common HibernateException is a generic error. You have to
either check the exception message or find out more about the cause by
calling getCause() on the exception.
■ A JDBCException is any exception thrown by Hibernate’s internal JDBC
layer. This kind of exception is always caused by a particular SQL statement,
and you can get the offending statement with getSQL(). The internal
exception thrown by the JDBC connection (the JDBC driver, actually) is
available with getSQLException() or getCause(), and the database- and
vendor-specific error code is available with getErrorCode().
■ Hibernate includes subtypes of JDBCException and an internal converter
that tries to translate the vendor-specific error code thrown by the database
driver into something more meaningful. The built-in converter can pro-
duce JDBCConnectionException, SQLGrammarException, LockAquisition-
Exception, DataException, and ConstraintViolationException for the
most important database dialects supported by Hibernate. You can either
manipulate or enhance the dialect for your database, or plug in a SQLEx-
ceptionConverterFactory to customize this conversion.
■ Other RuntimeExceptions thrown by Hibernate should also abort a transac-
tion. You should always make sure you catch RuntimeException, no matter
what you plan to do with any fine-grained exception-handling strategy.

You now know what exceptions you should catch and when to expect them. How-
ever, one question is probably on your mind: What should you do after you’ve
caught an exception?
All exceptions thrown by Hibernate are fatal. This means you have to roll back
the database transaction and close the current Session. You aren’t allowed to con-
tinue working with a Session that threw an exception.

Usually, you also have to exit the application after you close the Session fol-
lowing an exception, although there are some exceptions (for example, Stale-
ObjectStateException) that naturally lead to a new attempt (possibly after
interacting with the application user again) in a new Session.

No hay comentarios: