Hibernate 如何在弹出异常时提交事务

Hibernate how to commit transaction even when exception pops up

我在服务 A 中有一个方法

@Transactional
public void doSomething() {
  for (int i = 0; i < 100; i++) {
    anotherService.doThing();
  }
}

还有服务 B 中的另一种方法

@Transactional(propagation = REQUIRES_NEW, noRollbackFor = RuntimeException.class)
public void doThing() {
  ...
  try {
    repository.insertRandomValue();
  } catch (Exception ignored) {
  }      
  ...
}

我的问题是,例如,当“repository.insertRandomValue()”抛出 ConstraintViolationException 时,即使它在 catch() 中被捕获,线程也会以

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

我已尝试将传播设置为 REQUIRES_NEW 并尝试将事务管理器和 GlobalRollbackOnParticipationFailure 设置为 false。

@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
  JpaTransactionManager manager = new JpaTransactionManager(entityManagerFactory);
  manager.setGlobalRollbackOnParticipationFailure(false);
  return manager;
}

我希望它简单地忽略失败的插入尝试并继续工作。有人知道如何实现吗?

Hibernate 文档说的很清楚你要回滚(第 5.16 节异常处理):

If the JPA EntityManager or the Hibernate-specific Session throws an exception, including any JDBC SQLException, you have to immediately rollback the database transaction and close the current EntityManager or Session.

Certain methods of the JPA EntityManager or the Hibernate Session will not leave the Persistence Context in a consistent state. As a rule of thumb, no exception thrown by Hibernate can be treated as recoverable. Ensure that the Session will be closed by calling the close() method in a finally block.

Rolling back the database transaction does not put your business objects back into the state they were at the start of the transaction. This means that the database state and the business objects will be out of sync. Usually, this is not a problem because exceptions are not recoverable and you will have to start over after rollback anyway.

所以你需要事先检查是否会出现 ConstraintViolationException