知识点1.事务的传播机制 默认是REQUIRED,意思是内嵌方法如果也用了@Transactional注解,则与外层事务方法共用一个事务。即同一个事务。
外层方法methodA内嵌调用了 studuentService的methodA()方法
Studentservice的方法定义如下:
StuService.methodA()执行结果:全部插入失败,事务回滚。
原因:共用一个事务,该事务在StudentService 类的methodA中抛空指针异常时被打上回滚标记,注定会被rollback,即使在外层事务方法中对异常进行了捕获处理,事务依然会被回滚。
变种验证1:去掉StuService类的methodA事务注解,保留StudentService类的methodA事务注解。
StuService.methodA()执行结果:张三 40 这条数据插入成功,李四 50插入失败。
原因:外层方法弃用事务后,sql正常提交。内嵌方法使用了事务注解,事务回滚。
变种验证2:两个类的methodA都加事务注解,并且将StudentService methodA事务传播机制改为 REQUIRES_NEW,这样StuService 和 StudentService methodA()方法将使用两个独立的事务.
如图:
StuService.methodA()执行结果:张三 40 这条数据插入成功,李四 50插入失败。
原因:两个事务相互独立,外层方法对异常进行了捕获处理,不会回滚。内层事务有异常,会回滚。
-------------------------
知识点2:@Transactional注解默认只回滚 RuntimeException,不回滚IOException.
例:StudentService类和StuService 类的 methodB() 都带有事务注解@Transactional,且方法没有任何对异常的捕获处理。
StuService.methodB()执行结果:全部插入成功。
原因:@Transactional注解默认只回滚 RuntimeException,忽略了 IOException
变种验证:将两个Service的methodB()方法上的注解改为
@Transactional(rollbackFor = Exception.class)
StuService.methodB()执行结果:全部插入失败。
原因:事务对IOException做出了反应,作了回滚标记,事务最终回滚。
变种验证:去掉StuService methodB上的事务注解,弃用事务。StudentService methodB保留@Transactional(rollbackFor = Exception.class)
结果:StudentService methodB 事务回滚,插入失败。 而外层因为弃用了事务,插入成功。