当前位置: 首页 > 知识库问答 >
问题:

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

屠兴旺
2023-03-14

我在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\u NEW,并尝试将transaction manager和GlobalRollbackOnParticipationFailure设置为false。

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

我希望它只是忽略失败的插入攻击并继续工作。有人知道如何做到这一点吗?

共有1个答案

颜永怡
2023-03-14

Hibernate留档非常清楚您必须回滚(第5.16节异常处理):

如果JPA EntityManager或特定于Hibernate的会话抛出异常,包括任何JDBC SQLException,您必须立即回滚数据库事务并关闭当前的EntityManager或会话。

JPA EntityManager或Hibernate会话的某些方法不会使持久性上下文处于一致状态。根据经验,Hibernate抛出的任何异常都不能被视为可恢复的。通过在最终块中调用end()方法来确保会话将被关闭。

回滚数据库事务不会将业务对象恢复到事务开始时的状态。这意味着数据库状态和业务对象将不同步。通常,这不是问题,因为异常是不可恢复的,无论如何,在回滚后都必须重新开始。

因此,您需要事先检查是否存在ConstraintViolationException

 类似资料: