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

时间:2015-01-08 21:38:38

标签: java spring hibernate jpa transactions

@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);
}

dao.insert(e)中的methodB()导致主键违规并抛出ConstraintViolationException,这是RuntimeException的子类时,我希望该事务仍然可以提交我使用的noRollbackFor属性。但是我发现外部事务(在methodA上)仍然被HibernateTransactionManager回滚并带有消息

  

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

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

1 个答案:

答案 0 :(得分:11)

捕获到异常后,应丢弃Hibernate Session并回滚事务:

  

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

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

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