Avoid UnexpectedRollbackException with Spring Data JPA

Viewed 583

I've got a project with Spring Boot (2.3.3.RELEASE), Spring Data JPA (2.3.3.RELEASE) and Hibernate (5.4.20).

I'm trying to recover from DataIntegrityViolationException which happens after trying to save an Entity which violates a database constraint. For example:

@Transactional
public void doSomething() {

  // save some data into the database

  try {
    User user = new User();
    user.setName("test");

    // This method fails because of a constraint
    userService.save(user);
  } catch (DataIntegrityViolationException e) {
    LOGGER.info("Exception caught. Trying to recover...", e);
  }

  // continue doing other things
}

As I've caught the exception, when doSomething methods ends I expect that Spring would commit the changes. However, Spring throws the following exception:

org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only

As far as I've understood, Hibernate has marked the transaction as rollback-only when the integrity violation has happened and as a result Spring aborts the transaction.

I've tried to avoid this behaviour by adding @Transactional annotation with noRollbackFor attribute in the userService.save method, but it has been useless for this case.

I could create a new transaction for the userService.save method adding @Transactional(propagation = Propagation.REQUIRES_NEW) annotation. However, I want to keep all the changes in the same transaction.

Using plain JDBC there is no problem to recover from a DataIntegrityViolationException and commit the changes after all. ¿Is there any way to change this behaviour with Hibernate?

I've created a demo project in Github to check this behaviour: https://github.com/wearearima/hibernate-rollback

1 Answers

Unfortunately, it looks like this is not possible. Hibernate will always mark transaction as rollbackonly, when PersistenceException happens during flush due to "the persistence context might contain wrong data after a constraint violation" (quote of Christian Beikov)

Related