Spring事务传播机制

Spring事务传播机制

注:该篇文章所测试的皆是运行addEmpByRequired方法。

Propagation.REQUIRED

	当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中
/**************************************员工******************************************/
@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    @Autowired
    private DepartmentService departmentService;
    
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addEmpByRequired(String name) {
        Employee employee = new Employee();
        employee.setDeptId(1);
        employee.setName(name);
        employee.setAddress("邯郸");
        employeeMapper.insertSelective(employee);
        departmentService.addDept("jishubu");
        int i = 1/0;  //异常
    }
}

/**************************************部门******************************************/
@Service
public class DepartmentServiceImpl implements DepartmentService {

    @Autowired
    DepartmentMapper departmentMapper;

    @Override
    public void addDeptByRequired(String name) {
        Department department = new Department();
        department.setName(name);
        departmentMapper.insertSelective(department);
//        int i = 1/0;
    }
}

1.上述代码中,无论异常出现在哪里,添加员工和添加部门都会回滚。因为 REQUIRED 会让添加员工和添加部门变为一个事务。
2.若异常在addDept中,但是在addEmpByRequired把 addDept方法 捕捉了,则会抛出异常:Transaction rolled back because it has been marked as rollback-only 。
3.若在addDeptByRequired上添加@Transactional(propagation = Propagation.REQUIRED),在addEmpByRequired不添加事务,则addDeptByRequired是一个事务,addEmpByRequired并不是一个事务。因为addDeptByRequired开启了一个事务,但是addEmpByRequired并不存在一个事务中。

Propagation.SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行。
/*************************************员工***************************************/
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addEmpBySupports(String name) {
    Employee employee = new Employee();
    employee.setDeptId(2);
    employee.setName(name);
    employee.setAddress("邯郸");
    employeeMapper.insertSelective(employee);
    departmentService.addDeptBySupports("jishubu");
//  int i = 1/0;
}

/*************************************部门***************************************/
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public void addDeptBySupports(String name) {
    Department department = new Department();
    department.setName(name);
    departmentMapper.insertSelective(department);
    int i = 1/0;
}

1.该属性主要是添加在被调用者上。因为添加到调用者就不以事务的方式运行了。
2.如果调用者为事务,则被调用者也为事务。
3.如果调用者不是事务,则被调用者也不是事务。

Propagation.MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常。
/*************************************员工***************************************/
@Override
//@Transactional(propagation = Propagation.REQUIRED)
public void addEmpByMandatory(String name) {
    System.out.println("aaaaaa");
    Employee employee = new Employee();
    employee.setDeptId(3);
    employee.setName(name);
    employee.setAddress("邯郸");
    employeeMapper.insertSelective(employee);
    departmentService.addDeptByMandatory("jishubu");
    int i = 1/0;
}

/*************************************部门***************************************/
@Override
@Transactional(propagation = Propagation.MANDATORY)
public void addDeptByMandatory(String name) {
    Department department = new Department();
    department.setName(name);
    departmentMapper.insertSelective(department);
    int i = 1/0;
}

1.该属性是添加到被调用者上,如果添加到调用者上,则直接抛出异常。
2.添加到被调用者上, 如果调用者有事务,则被调用者加入到调用者的事务中。

Propagation.REQUIRES_NEW

新建事务,如果当前存在事务,把当前事务挂起
/*************************************员工***************************************/
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addEmpByRequiresNew(String name) {
    Employee employee = new Employee();
    employee.setDeptId(4);
    employee.setName(name);
    employee.setAddress("邯郸");
    employeeMapper.insertSelective(employee);
    departmentService.addDeptByRequiresNew("jishubu");
    int i = 1/0;
}

/*************************************部门***************************************/
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addDeptByRequiresNew(String name) {
    Department department = new Department();
    department.setName(name);
    departmentMapper.insertSelective(department);
//int i = 1/0;
}

1.该属性应该是除了REQUIRED用的最多的。
2.也是针对被调用者的。
3.不管调用者是否存在事务,被调用者都会新开一个事务,相当于被调用者都存在于自己的事务中和调用者没有关系。
如上述代码,addEmpByRequiresNew会回滚,但addDeptByRequiresNew不会回滚。因为他们是两个事务。

Propagation.NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
/*************************************员工***************************************/
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addEmpByNotSupported(String name) {
    Employee employee = new Employee();
    employee.setDeptId(5);
    employee.setName(name);
    employee.setAddress("邯郸");
    employeeMapper.insertSelective(employee);
    departmentService.addDeptByNotSupported("jishubu");
    int i = 1/0;
}

/*************************************部门***************************************/
@Override
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void addDeptByNotSupported(String name) {
    Department department = new Department();
    department.setName(name);
    departmentMapper.insertSelective(department);
    int i = 1/0;
}

1.该属性如果放在调用者上,则是以非事务方式运行。
2.如果放在被调用者上,该方法以非事务运行,调用者如果有事务,则运行单独的事务(挂起)。
上述代码,会出现添加员工回滚,添加部门不回滚。

Propagation.NEVER

以非事务方式执行,如果当前存在事务,则抛出异常。
/*************************************员工***************************************/
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addEmpByNever(String name) {
    Employee employee = new Employee();
    employee.setDeptId(6);
    employee.setName(name);
    employee.setAddress("邯郸");
    employeeMapper.insertSelective(employee);
    departmentService.addDeptByNever("jishubu");
    int i = 1/0;
}


/*************************************部门***************************************/
@Override
@Transactional(propagation = Propagation.NEVER)
public void addDeptByNever(String name) {
    Department department = new Department();
    department.setName(name);
    departmentMapper.insertSelective(department);
    int i = 1/0;
}

1.该属性如果在调用者上,则直接以非事务运行。
2.如果作用在被调用者上,则看调用者是否有事务,如果调用者有事务,则抛出异常,如果没有事务,则以非事务运行。
上述代码中,则会抛出异常。(并不是除0异常,而是:Existing transaction found for transaction marked with propagation ‘never’)

Propagation.NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
(这个和REQUIRED区别在于一个是加入到一个事务,一个是在嵌套事务运行)
/*************************************员工***************************************/
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addEmpByNested(String name) {
    Employee employee = new Employee();
    employee.setDeptId(7);
    employee.setName(name);
    employee.setAddress("邯郸");
    employeeMapper.insertSelective(employee);
    try {
        departmentService.addDeptByNested("jishubu");
    }catch (Exception e){

    }
//  int i = 1/0;
}

/*************************************部门***************************************/
@Override
@Transactional(propagation = Propagation.NESTED)
public void addDeptByNested(String name) {
    Department department = new Department();
    department.setName(name);
    departmentMapper.insertSelective(department);
    int i = 1/0;
}

1.可以这么理解,大多数情况下,效果和REQUIRED一样。但是有一种情况,就是上述代码中,被调用者事务传播属性为NESTED,当出现异常时, 调用者把部门实现类异常捕捉了。这个区别与REQUIRED的并不会报错,而且调用者不会回滚,只有被调用者回滚了。
大概原理:当被调用者使用PROPAGATION_NESTED时,底层的数据源必须基于JDBC 3.0,并且实现者需要支持保存点事务机制。
2.按上述代码来说(去掉捕捉),当执行到被调用者这个方法时,Spring会为它创建一个内部的嵌套事务,如果被调用者执行失败,则事务回滚到被调用者之前的点,此时如果不抛异常,则不会回滚。这个嵌套事务,是调用者的一部分,只有外层事务提交了,内层的嵌套事务才会一起提交,这也是与REQUIRED(加入事务),REQUIRES_NEW(开启新事务)的区别。
还值得一提的是,NESTED是嵌套的意思,其实并不是只有NESTED用于嵌套,只要理解上述7个传播机制的意思,都可以嵌套用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值