Spring transaction: rollback on Exception or Throwable
As I understand catching Error will help us behave correctly even when something really bad happen. Or maybe it wouldn't help?
You don't need to explicitly specify rollbackFor = Throwable.class
, because spring will by default rollback the transaction if an Error
occurs.
See 12.5.3 Rolling back a declarative transaction
In its default configuration, the Spring Framework's transaction infrastructure code only marks a transaction for rollback in the case of runtime, unchecked exceptions; that is, when the thrown exception is an instance or subclass of RuntimeException. (Errors will also - by default - result in a rollback). Checked exceptions that are thrown from a transactional method do not result in rollback in the default configuration.
Or take a look at the DefaultTransactionAttribute
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
Since you are using @Transactional
, we can safely assume you are doing your database operations through Spring, Hibernate, or other JDBC wrappers. These JDBC wrappers don't typically throw checked exceptions, they throw runtime exceptions that wrap the JDBC SQLException
types.
@Transactional
is setup to rollback, by default, only when an unchecked exception is thrown.
Consider a use case like so
@Transactional
public void persistAndWrite(Bean someBean) throws IOException {
// DB operation
getSession().save(someBean);
// File IO operation which throws IOException
someFileService.writeToFile(someBean);
}
You wouldn't necessarily want to rollback the DB operation just because we couldn't write something to a file.
Similarly
@Transactional
public void persistAndThrowOutOfMemory(Bean someBean) {
// DB operation
getSession().save(someBean);
// consumes all memory, throws OutOfMemoryError
someService.hugeOperationThrowsOutOfMemoryError();
}
You wouldn't necessarily want to rollback the saved entity just because some service cause too much memory to be consumed.
@Transactional
gives you the option. Use it where appropriate.