Pavel S.
Pavel S.

Reputation: 1224

Spring's persistence exception translation not working with Hibernate 5

I am using Spring 4.3.10 and Hibernate 5.2.10 (I've migrated from Hibernate 4 since which moment got into below problem). The following post-processor is declared in order to take advantage of Spring's translation of Hibernate exceptions in my @Repository-marked service.

@Bean
public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
   return new PersistenceExceptionTranslationPostProcessor();
}

My code violates a DB constraint, so Hibernate will throw a org.hibernate.exception.ConstraintViolationException which I expect to translate into Spring's generic org.springframework.dao.DataIntegrityViolationException. However, what was working in Hibernate 4 does not in 5.

As I see from the source code, Hibernate 5 uses internally its ExceptionConverter which wraps the ConstraintViolationException with a JPA's javax.persistence.PersistenceException. Here's how Spring's LocalSessionFactoryBean's translateExceptionIfPossible() (inherited from HibernateExceptionTranslator) looks like:

@Override
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
   if (ex instanceof HibernateException) {
      return convertHibernateAccessException((HibernateException) ex);
   }
   return null;
}

An instance of PersistenceException instead of a bare Hibernate exception comes here, so translation won't happen.

I still admit the problem is mine as I couldn't find anyone facing this problem with such a popular usage. Any Ideas? Thanks!

Upvotes: 0

Views: 1287

Answers (1)

Pavel S.
Pavel S.

Reputation: 1224

It was a configuration issue. The problem was in spring-orm library which was of version 4.3.1 while the rest of Spring components were of 4.3.10. In the newer version, HibernateExceptionTranslator.translateExceptionIfPossible() looks upgraded:

@Override
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
   if (ex instanceof HibernateException) {
      return convertHibernateAccessException((HibernateException) ex);
   }
   if (ex instanceof PersistenceException) {
      if (ex.getCause() instanceof HibernateException) {
         // this is my case!
         return convertHibernateAccessException((HibernateException) ex.getCause());
      }
      return EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(ex);
   }
   return null;
}

Now it works as expected.

Upvotes: 1

Related Questions