实验七 事务属性:事务传播行为
1、引入事务传播行为
①Service方法应用了通知
②过滤器或拦截器等类似组件
2、事务传播行为要研究的问题
3、propagation属性
4、测试
①创建测试方法
[1]在EmpService中声明两个内层方法
[2]创建TopService
[3]junit测试方法
②测试 REQUIRED 模式
③测试 REQUIRES_NEW 模式
[1]修改 EmpService 中内层方法
[2]执行流程

实验七 事务属性:事务传播行为

1、引入事务传播行为

在大多数情况下,我们会认为事务操作要么都成功,要么回到初始状态。比如下订单,如果主订单添加成功,三个订单明细添加成功两个,总额就对不上了,顾客最终收货会有减少的。这种情况肯定要保证全部成功。类似还有银行转账例子。但也存在不同的需求,比如:

①Service方法应用了通知

实验七 事务属性:事务传播行为 - 图1

②过滤器或拦截器等类似组件

实验七 事务属性:事务传播行为 - 图2

2、事务传播行为要研究的问题

实验七 事务属性:事务传播行为 - 图3

3、propagation属性

@Transactional 注解通过 propagation 属性设置事务的传播行为。propagation 属性的可选值由 org.springframework.transaction.annotation.Propagation 枚举类提供:

名称 含义
REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是默认值。
REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED 如当前存在事务,则在嵌套事务内执行。如当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作

4、测试

①创建测试方法

[1]在EmpService中声明两个内层方法

@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public void updateEmpNameInner(Integer empId, String empName) {

  1. empDao.updateEmpNameById(empId, empName);<br />}

@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public void updateEmpSalaryInner(Integer empId, Double empSalary) {

empDao.updateEmpSalaryById(empId, empSalary);<br />}

[2]创建TopService

实验七 事务属性:事务传播行为 - 图4

@Service
public class TopService {

// 这里我们只是为了测试事务传播行为,临时在Service中装配另一个Service<br />    // 实际开发时非常不建议这么做,因为这样会严重破坏项目的结构<br />    @Autowired<br />    private EmpService empService;

@Transactional<br />    public void topTxMethod() {

    // 在外层方法中调用两个内层方法<br />        empService.updateEmpNameInner(2, "aaa");

    empService.updateEmpSalaryInner(3, 666.66);<br />    }

}

[3]junit测试方法

@Autowired
private TopService topService;

@Test
public void testPropagation() {

// 调用外层方法<br />    topService.topTxMethod();

}

②测试 REQUIRED 模式

实验七 事务属性:事务传播行为 - 图5

效果:内层方法A、内层方法B所做的修改都没有生效,总事务回滚了。

③测试 REQUIRES_NEW 模式

[1]修改 EmpService 中内层方法

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void updateEmpNameInner(Integer empId, String empName) {

empDao.updateEmpNameById(empId, empName);<br />}

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void updateEmpSalaryInner(Integer empId, Double empSalary) {

empDao.updateEmpSalaryById(empId, empSalary);<br />}

[2]执行流程

实验七 事务属性:事务传播行为 - 图6

外层方法依次调用内层方法A,内层方法B,会挂起外层方法的事务,新开内层方法A的事务,内层方法B的事务。如果内层方法A执行成功,内层方法B执行出现异常,则内层方法B事务会回滚,外层方法事务也会回滚,但是内层方法A事务已经提交,不会回滚。

上一个实验 回目录