分析和总结spring事务REQUIRES_NEW,REQUIRED的区别

REQUIRES_NEW的使用特性 即创建一个新事务,如果当前事务存在,则挂起当前事务。

REQUIRED的使用特性 即支持当前事务,如果不存在,则创建一个新事务。

模拟外层出现异常

TransactionalTest
package com.xiaobu.junit;

import com.xiaobu.entity.Persons;
import com.xiaobu.entity.Salary;
import com.xiaobu.service.PersonsService;
import com.xiaobu.service.SalaryService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author xiaobu
 * @version JDK1.8.0_171
 * @date on  2021/10/27 16:36
 */
@SpringBootTest
public class TransactionalTest {
    @Autowired
    private PersonsService personsService;
    @Autowired
    private SalaryService salaryService;

    @Test
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void test() {
        //add persons
        Persons persons = new Persons();
        persons.setFirstName("admin");
        personsService.insert(persons);
        //add salary
        Salary salary = Salary.builder().salary("100").userId(100).build();
        salaryService.insert(salary);
        //模拟出现了异常情况 结果:persons插入失败 salary插入成功
        int i = 1 / 0;
    }

}

PersonsService
package com.xiaobu.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaobu.entity.Persons;
import com.xiaobu.mapper.PersonsMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * The type Persons service.
 *
 * @author xiaobu
 * @version 1.0.0
 * @className PersonsService.java
 * @createTime 2021年11月17日 19:25:00
 */
@Service
public class PersonsService extends ServiceImpl<PersonsMapper, Persons> {
    @Resource
    private PersonsMapper personsMapper;

    /**
     * Insert int.
     *
     * @param p the p
     * @return the int
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void insert(Persons p) {
        personsMapper.insert(p);
    }

}


SalaryService
package com.xiaobu.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaobu.entity.Salary;
import com.xiaobu.mapper.SalaryMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @author xiaobu
 * @version 1.0.0
 * @className SalaryService.java
 * @createTime 2021年11月25日 09:52:00
 */

@Service
public class SalaryService extends ServiceImpl<SalaryMapper, Salary> {

    @Resource
    private SalaryMapper salaryMapper;


    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void insert(Salary s) {
        salaryMapper.insertSelective(s);
    }

}

模拟REQUIRES_NEW修饰方法出现异常情况,看看它是否对外层造成影响。

TransactionalTest
package com.xiaobu.junit;

import com.xiaobu.entity.Persons;
import com.xiaobu.entity.Salary;
import com.xiaobu.service.PersonsService;
import com.xiaobu.service.SalaryService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author xiaobu
 * @version JDK1.8.0_171
 * @date on  2021/10/27 16:36
 */
@SpringBootTest
public class TransactionalTest {
    @Autowired
    private PersonsService personsService;
    @Autowired
    private SalaryService salaryService;

    @Test
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void test() {
        //add persons
        Persons persons = new Persons();
        persons.setFirstName("admin");
        personsService.insert(persons);
        //add salary
        Salary salary = Salary.builder().salary("100").userId(100).build();
        salaryService.insert(salary);
    }

}

    @Test
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public void test(){
        //add persons
        Persons persons=new Persons();
        persons.setFirstName("admin126");
        personsService.insert(persons);
        //add salary
        Salary salary=Salary.builder().salary("100").userId(100).build();
        salaryService.insert(salary);
        int i=1/0;
        }

执行结果我们发现,外层事务出现异常,用户表更新操作被回滚,但REQUIRES_NEW修饰的salaryService.insert方法执行成功。

PersonsService
package com.xiaobu.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaobu.entity.Persons;
import com.xiaobu.mapper.PersonsMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * The type Persons service.
 *
 * @author xiaobu
 * @version 1.0.0
 * @className PersonsService.java
 * @createTime 2021年11月17日 19:25:00
 */
@Service
public class PersonsService extends ServiceImpl<PersonsMapper, Persons> {
    @Resource
    private PersonsMapper personsMapper;

    /**
     * Insert int.
     *
     * @param p the p
     * @return the int
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void insert(Persons p) {
        personsMapper.insert(p);
    }

}


SalaryService
package com.xiaobu.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaobu.entity.Salary;
import com.xiaobu.mapper.SalaryMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @author xiaobu
 * @version 1.0.0
 * @className SalaryService.java
 * @createTime 2021年11月25日 09:52:00
 */

@Service
public class SalaryService extends ServiceImpl<SalaryMapper, Salary> {

    @Resource
    private SalaryMapper salaryMapper;


    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void insert(Salary s) {
        salaryMapper.insertSelective(s);
        // 模拟REQUIRES_NEW修饰方法出现异常情况,看看它是否对外层造成影响。
        int i = 1 / 0;

    }

}

结果:persons和salary都未插入数据

总结,REQUIRES_NEW修饰方法的特性:它会对外层的事务有影响,如果它里面执行时出现异常不仅自己的内容回滚,也会导致外层事务也回滚

REQUIRES_NEW的事务,不受外层调用者影响,但会影响外层的事务。 REQUIRED的事务,即受外层调用者影响,也会影响外层的事务。

实际业务如何使用: 在同一个方法中,因为大多数情况是一系列业务要保证要么都成功要么都失败的,所以各个业务方法使用默认的REQUIRED方式即可。
如果中间有一个特殊的业务方法,和其他业务不关联,我们可以给它的方法设置REQUIRES_NEW,这样就能保证其他业务有异常时,它也不会被回滚。

参考:

分析和总结spring事务REQUIRES_NEW,REQUIRED的区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值