The JpaTransactionManager seems to have a nice piece of functionality that translates an exception thrown by Hibernate.
For example it will call translateExceptionIfPossible in doCommit and we will get a specific exception somewhere in the org.springframework.dao.DataAccessException hierarchy.
For example org.hibernate.StaleStateException will get wrapped into a JpaOptimisticLockingFailureException.
The JtaTransactionManger has no such call and seems to bundle all of my Hibernate exceptions into UnexpectedRollbackException exception.
Not sure if this is a bug but it seems inconsistent and also we lose all of the specific exception type information.
Affects: 3.1 GA
The text was updated successfully, but these errors were encountered:
I'm afraid that this comes as a consequence of the design of JTA as well as JPA: There is no separate flush step before commit in JPA, so flushing always happens as part of the canonical commit call - which in this case comes from JTA. And with JTA, it really is the JTA provider dealing with underlying synchronization exceptions, deciding to dumb them down into the JTA exception hierarchy...
We could theoretically unwrap JTA exceptions and try to find native JPA exceptions underneath, but unfortunately there is no proper contract for this. A JTA provider is not even required to preserve the original exception at all - and could in practice wrap a native exception in any number of its own provider exceptions.
One way around this is to explicitly flush the EntityManager in a repository bean and catch the JPA OptimisticLockException right on the spot there - before commit. When using persistence exception translation, a bean higher up the call stack (which calls into the repository bean through a proxy) could even catch Spring's translated OptimisticLockingFailureException that way.
I still don't understand why it is not possible to translate the underlying exception type with JTA. (The JPA manager seems to do exactly that).
In simplest terms it means: We are in some java function and we get an exception thrown at us, we wrap it and throw it again.
Is there some uncertainty about which underlying exceptions we are getting from the underlying layers when we are the JTA manager?
Also I don't understand when you say 'unwrap JTA exceptions'. The JTA manager is a Spring class and it is deciding itself what exception to throw. It would not need to unwrap anything but only look at what exception it got.