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

@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)中的dao.insert(e)导致主键冲突并抛出一个ConstraintViolationException (它是RuntimeException的子类)时,由于我使用的noRollbackFor属性,我希望该事务仍然提交。 但是我发现外部事务(在methodA )仍然被HibernateTransactionManager和消息回滚

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

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

捕获exception后,应丢弃Hibernate会话并回滚事务:

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

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

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