1. 回滚规则
Spring 默认情况下,只会在遇到运行时异常(如 RuntimeException 或其子类)时回滚,而检查型异常(如 IOException 或 SQLException)不会自动回滚,除非你特别配置。
可以通过 @Transactional 注解中的 rollbackFor 或 noRollbackFor 来指定需要回滚的异常类型。
@Transactional(rollbackFor = Exception.class)
public void someMethod() {
// 方法体
}
2. 事务传播行为(Propagation)
事务传播行为决定了一个事务方法在另一个事务上下文中的执行方式。对于大小子事务,最常见的传播行为是:
- REQUIRED(默认传播行为): 如果当前方法没有事务,它将启动一个新的事务;如果当前方法已经存在事务,它将加入到当前事务中。父事务会影响子事务的回滚。
- REQUIRES_NEW: 当前方法总是会启动一个新的事务,并且挂起当前事务。如果父事务回滚,子事务仍然会提交(反之亦然)。
- NESTED: 当前方法会在父事务内启动一个嵌套事务,父事务回滚时会回滚嵌套事务,但是如果子事务回滚,父事务可能不会回滚,除非嵌套事务显式指定。
3. 大小事务的回滚
在父子事务的回滚中,具体的回滚行为会受到传播行为的影响:
父事务回滚
- 如果父事务发生回滚,所有子事务(传播行为是 REQUIRED 或 NESTED)都会回滚。
- 对于 REQUIRES_NEW 的传播行为,父事务的回滚不会影响子事务的提交。子事务会独立处理回滚或提交。
子事务回滚
- 如果子事务回滚,父事务会根据传播行为来决定是否回滚。例如,REQUIRES_NEW 传播行为的子事务的回滚不会影响父事务,但 REQUIRED 和 NESTED 会根据回滚规则进行相应的处理。
4. 例子:父子事务回滚
@Service
public class TransactionService {
@Transactional
public void parentMethod() {
try {
// 父事务中的操作
childMethod(); // 子事务
} catch (Exception e) {
// 捕获异常后父事务将会回滚
throw new RuntimeException("父事务回滚");
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void childMethod() {
// 子事务中的操作,若发生异常仅子事务回滚
throw new RuntimeException("子事务回滚");
}
}
- 父事务的传播行为是默认的 REQUIRED,当发生异常时,父事务会回滚。
- 子事务的传播行为是 REQUIRES_NEW,即使子事务回滚,父事务仍然可以提交。
5. 总结
父事务回滚:父事务的回滚会导致所有子事务回滚,除非子事务使用 REQUIRES_NEW 传播行为。
子事务回滚:子事务的回滚会影响父事务的回滚,具体影响取决于传播行为(如 REQUIRES_NEW 会忽略父事务的回滚)

460

被折叠的 条评论
为什么被折叠?



