@Transactional (noRollbackFor=RuntimeException.class) 不阻止 RuntimeException 上的回滚

2022-09-03 13:02:59
@Transactional (noRollbackFor=RuntimeException.class)
public void methodA (Entity e){
   service.methodB(e);
}

---服务方法如下---

@Transactional (propagation=Propagation.REQUIRES_NEW, noRollbackFor=RuntimeException.class)
public void methodB (Entity e){
   dao.insert(e);
}

当 in 导致主键冲突并抛出一个 ,这是 的子类,我希望事务仍然会因为我使用的属性而提交。但是我观察到外部事务(on)仍然被消息回滚dao.insert(e)methodB()ConstraintViolationExceptionRuntimeExceptionnoRollbackFormethodAHibernateTransactionManager

org.springframework.transaction.UnexpectedRollback Exception:事务已回滚,因为它已被标记为仅回滚

我发现了类似的问题,但并不完全是这个问题。


答案 1

一旦捕获到异常,休眠会话应被丢弃,事务应回滚:

如果会话引发异常,则必须回滚事务并丢弃会话。发生异常后,会话的内部状态可能与数据库不一致。

因此,适用于可能引发异常的服务和 DAO 层。假设您有一个网关服务,它通过 Hibernate DAO 写入数据库,并通过电子邮件服务发送电子邮件。如果 emailService 引发 ,您可以指示网关服务在捕获此异常时不回滚:noRollbackForSendMailFailureException

@Transactional(noRollbackFor=SendMailFailureException.class)
public void saveAndSend(Entity e){
   dao.save(e);
   emailService.send(new Email(e));
}

答案 2

推荐