Spring事务场景下,createLog私有方法异常是否触发事务回滚?
问题解答:私有createLog方法异常是否触发事务回滚?
相关代码
PersonManager类
@Service @RequiredArgsConstructor @Slf4j public class PersonManager { @Transactional public void updatePerson(PersonPayload personPayload, String uid) { Person person = personRepository.findByUid(uid); personProcessManager.createLog(person); Person personDuplicate = new Person(); personDuplicate.copyPerson(person); personMapper.updatePerson(personPayload,personDuplicate); personRepository.save(person); personRepository.save(personDuplicate); personProcessManager.createLog(personDuplicate); } }
PersonProcessManager类
@Service @RequiredArgsConstructor @Slf4j public class PersonProcessManager { @Transactional public Log createLog(Person person) { return createLog(person, LogTypeEnum.CHANGE.getId(), LogStatusEnum.COPY.getId()); } private Log createLog(Person person, Long logTypeId, Long statusLogId) { Log log = new Log(); log.setLogType(1); log.setLogStatus(2); log.setDateCreation(LocalDate.now()); log.setPerson(person); return logRepository.save(person); } }
问题分析与结论
当PersonProcessManager的私有createLog方法抛出异常时,会触发整个事务回滚,具体原因如下:
- 事务传播逻辑:
PersonManager.updatePerson方法标注了@Transactional,启动了一个全局事务;PersonProcessManager.createLog方法的@Transactional默认使用REQUIRED传播行为,会直接加入到当前已存在的事务中,不会创建独立事务。 - 异常传递路径:私有方法抛出的异常会向上传递到公共的
createLog方法,如果这个异常是Spring默认支持回滚的类型(RuntimeException或Error),且没有被任何代码捕获处理,最终会扩散到updatePerson方法的事务上下文里。 - 回滚触发规则:Spring的
@Transactional默认只对RuntimeException和Error执行回滚操作。只要异常未被捕获并正常抛出,updatePerson方法中所有已执行的数据库操作(包括personRepository.save(person)、personRepository.save(personDuplicate)等)都会被全部回滚。
另外注意代码里的一处明显错误:私有createLog方法最后调用logRepository.save(person),这里应该传入创建好的log对象而非person,这大概率是引发异常的直接原因。
内容的提问来源于stack exchange,提问作者robert trudel
相关产品推荐
相关产品推荐

