Spring 事务传播行为-其中类型功能测试

原创 2018年04月15日 17:11:20

spring事务有如下七种类型

  • REQUIRED 默认,需要事务,没有则新建
  • REQUIRED_NEW 需要新事务,每次都新建
  • SUPPORTS 支持事务但不强制有事务
  • NOT_SUPPORTS 不支持事务,有事务挂起事务,执行完方法再唤醒
  • MONDATORY 强制事务,没有事务抛出异常
  • NEVER 当前方法不能有事务,否则抛出异常
  • NESTED 嵌套事务,无论是否有事务都会创建一个内部事务事务,内部回滚外部不回滚,外部回滚内部回滚

测试代码

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class UserServiceTest {

    @Autowired UserService service;

    //////////////////////////////////////////////////////////////////
    //   可以发现在调用方法中有事务的话,被调用方法不会新建事务,直接执行
    //   可以发现在调用方法中没有事务的话,会新建一个事务用于执行
    //////////////////////////////////////////////////////////////////
    @Test
    public void testTransaction1() throws Exception {
        service.testRequiredNoTransaction();
    }

    @Test
    public void testTransaction2() throws Exception {
        service.testRequiredHasTransaction();
    }

    //////////////////////////////////////////////////////////////////
    //   可以发现无论有没有事务,supports都不会去创建一个事务
    //////////////////////////////////////////////////////////////////

    @Test
    public void testTransaction3() throws Exception {
        service.testSupportsOfHasTransaction();
    }


    @Test
    public void testTransaction4() throws Exception {
        service.testSupportsOfNoTransaction();
    }



    //////////////////////////////////////////////////////////////////
    //   可以发现无论有没有事务,required都会创建一个事务
    //////////////////////////////////////////////////////////////////

    @Test
    public void testTransaction5() throws Exception {
        service.testRequiredNewOfHasTransaction();
    }


    @Test
    public void testTransaction6() throws Exception {
        service.testRequiredNewOfNoTransaction();
    }

    //////////////////////////////////////////////////////////////////
    // mandatory在没有事务的环境下会抛出异常IllegalTransactionStateException
    // mandatory在由事务的环境下正常运行
    //////////////////////////////////////////////////////////////////

    @Test
    public void testTransaction7() throws Exception {
        try {
            service.testMandatoryOfNoTransaction();
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    @Test
    public void testTransaction8() throws Exception {
        try {
            service.testMandatoryOfHasTransaction();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //////////////////////////////////////////////////////////////////
    // nested 默认会创建一个nested transaction
    // 在外层事务抛出异常下,内层事务会回滚 test11
    // 在内层事务抛出异常下,外层事务不会回滚 test12
    //
    //////////////////////////////////////////////////////////////////

    @Test
    public void testTransaction9() throws Exception {
        try {
            service.testNestedOfNoTransaction();
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    @Test
    public void testTransaction10() throws Exception {
        try {
            service.testNestedOfHasTransaction();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Test
    public void testTransaction11() throws Exception {
        try {
            service.testNestedOfHasTransactionWithException();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Test
    public void testTransaction12() throws Exception {
        try {
            service.testNestedOfHasTransactionWithNestedException();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //////////////////////////////////////////////////////////////////
    // never在有事务的环境下会抛出异常IllegalTransactionStateException
    // never在没有事务的环境下正常运行,与mandatory正好相反
    //////////////////////////////////////////////////////////////////

    @Test
    public void testTransaction13() throws Exception {
        try {
            service.testNeverOfNoTransaction();
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    @Test
    public void testTransaction14() throws Exception {
        try {
            service.testNeverOfHasTransaction();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //////////////////////////////////////////////////////////////////
    // not_supported 在有事务的环境下会将当前事务挂起,执行完当前方法结束会再把事务唤醒
    // not_supported 在没有事务的环境下直接运行。不等待
    //////////////////////////////////////////////////////////////////

    @Test
    public void testTransaction15() throws Exception {
        try {
            service.testNotSupportedOfHasTransaction();
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    @Test
    public void testTransaction16() throws Exception {
        try {
            service.testNotSupportedOfNoTransaction();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

外部事务(或者被称为事务调用方)


@Service
public class UserService {

    @Autowired
    ShopService shopService;

    private final UserMapper mapper;

    @Autowired
    public UserService(UserMapper mapper) {
        this.mapper = mapper;
    }

    public User findByName(String name) {
        return mapper.selectByPrimaryKey(name);
    }

    @Transactional
    public int updateUser(User user) {
        mapper.updateByPrimaryKeySelective(user);
        Object proxy = AopContext.currentProxy();
        System.out.println(proxy);
        throw new BaseException("-1", "我就不想让你更新成功");
    }

    //////////////////////////////////////////////////////////////////////////////////////////////


    public void testRequiredNoTransaction(){
        //shopService.testA();
        System.out.println(">>>>>>>>>>>>>>>> 我没有事务,我调用一个事务传播行为Propagation.REQUIRED,开始");
        shopService.testTransaction1();
        System.out.println(">>>>>>>>>>>>>>>> 我没有事务,我调用一个事务传播行为Propagation.REQUIRED,结束");
    }

    @Transactional
    public void testRequiredHasTransaction(){
        //shopService.testA();
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.REQUIRED,开始");
        shopService.testTransaction1();
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.REQUIRED,结束");
    }

    //////////////////////////////////////////////////////////////////////////////////////////////

    @Transactional
    public void testSupportsOfHasTransaction(){
        //shopService.testA();
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.SUPPORTS,开始");
        shopService.testTransactionSupports();
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.SUPPORTS,结束");
    }


    public void testSupportsOfNoTransaction(){
        //shopService.testA();
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.SUPPORTS,开始");
        shopService.testTransactionSupports();
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.SUPPORTS,结束");
    }

    //////////////////////////////////////////////////////////////////////////////////////////////

    @Transactional
    public void testRequiredNewOfHasTransaction() {
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.REQUIRED_NEW,开始");
        shopService.testTransactionRequiredNew();
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.REQUIRED_NEW,结束");
    }

    public void testRequiredNewOfNoTransaction() {
        System.out.println(">>>>>>>>>>>>>>>> 我没事务,我调用一个事务传播行为Propagation.REQUIRED_NEW,开始");
        shopService.testTransactionRequiredNew();
        System.out.println(">>>>>>>>>>>>>>>> 我没事务,我调用一个事务传播行为Propagation.REQUIRED_NEW,结束");
    }

    //////////////////////////////////////////////////////////////////////////////////////////////

    @Transactional
    public void testMandatoryOfHasTransaction() {
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.MANDATORY,开始");
        shopService.testTransactionMandatory();
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.MANDATORY,结束");
    }

    public void testMandatoryOfNoTransaction() {
        System.out.println(">>>>>>>>>>>>>>>> 我没事务,我调用一个事务传播行为Propagation.MANDATORY,开始");
        shopService.testTransactionMandatory();
        System.out.println(">>>>>>>>>>>>>>>> 我没事务,我调用一个事务传播行为Propagation.MANDATORY,结束");
    }

    //////////////////////////////////////////////////////////////////////////////////////////////

    @Transactional
    public void testNestedOfHasTransaction() {
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.NESTED,开始");
        shopService.testTransactionNested();
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.NESTED,结束");
    }


    @Transactional
    public void testNestedOfHasTransactionWithException() {
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.NESTED,开始");
        shopService.testTransactionNested();
        throw new BaseException("-1", "外层调用函数抛出异常!!");
    }

    @Transactional
    public void testNestedOfHasTransactionWithNestedException() {
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.NESTED,开始");
        User user = new User();
        user.setName("wuhulala");
        user.setRemark("内层事务回滚。外层事务不回滚!!!");
        mapper.updateByPrimaryKeySelective(user);
        try {
            shopService.testTransactionNestedWithException();
        } catch (Exception e){
            // do nothing
        }
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.NESTED,结束");
    }

    public void testNestedOfNoTransaction() {
        System.out.println(">>>>>>>>>>>>>>>> 我没事务,我调用一个事务传播行为Propagation.NESTED,开始");
        shopService.testTransactionNested();
        System.out.println(">>>>>>>>>>>>>>>> 我没事务,我调用一个事务传播行为Propagation.NESTED,结束");
    }

    //////////////////////////////////////////////////////////////////////////////////////////////

    @Transactional
    public void testNeverOfHasTransaction() {
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.NEVER,开始");
        shopService.testTransactionNever();
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.NEVER,结束");
    }

    public void testNeverOfNoTransaction() {
        System.out.println(">>>>>>>>>>>>>>>> 我没事务,我调用一个事务传播行为Propagation.NEVER,开始");
        shopService.testTransactionNever();
        System.out.println(">>>>>>>>>>>>>>>> 我没事务,我调用一个事务传播行为Propagation.NEVER,结束");
    }

    //////////////////////////////////////////////////////////////////////////////////////////////

    @Transactional
    public void testNotSupportedOfHasTransaction() {
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.NOT_SUPPORTED,开始");
        shopService.testTransactionNotSupported();
        System.out.println(">>>>>>>>>>>>>>>> 我有事务,我调用一个事务传播行为Propagation.NOT_SUPPORTED,结束");
    }

    public void testNotSupportedOfNoTransaction() {
        System.out.println(">>>>>>>>>>>>>>>> 我没事务,我调用一个事务传播行为Propagation.NOT_SUPPORTED,开始");
        shopService.testTransactionNotSupported();
        System.out.println(">>>>>>>>>>>>>>>> 我没事务,我调用一个事务传播行为Propagation.NOT_SUPPORTED,结束");
    }
}

内部事务(或者称为被调用事务方)

@Service
public class ShopService {


    @Autowired
    private UserMapper userMapper;


    @Transactional(propagation = Propagation.REQUIRED)
    public void testTransaction1() {
        System.out.println("我就是测试事务传播行为PROPAGATION_REQUIRED的");
        System.out.println("表示当前方法必须在一个具有事务的上下文中运行,如有客户端有事务在进行,那么被调用端将在该事务中运行,否则的话重新开启一个事务。(如果被调用端发生异常,那么调用端和被调用端事务都将回滚)");
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public void testTransactionSupports() {
        System.out.println("我就是测试事务传播行为PROPAGATION_SUPPORTS的");
        System.out.println("表示当前方法不必需要具有一个事务上下文,但是如果有一个事务的话,它也可以在这个事务中运行\n" +
                "\n");
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void testTransactionMandatory() {
        System.out.println("表示当前方法必须在一个事务中运行,如果没有事务,将抛出异常");
        System.out.println("我就是测试事务传播行为PROPAGATION_MANDATORY的");
    }


    @Transactional(propagation = Propagation.NESTED)
    public void testTransactionNested() {
        System.out.println("我就是测试事务传播行为PROPAGATION_NESTED的");
        System.out.println("表示如果当前方法正有一个事务在运行中,则该方法应该运行在一个嵌套事务中,\n" +
                "被嵌套的事务可以独立于被封装的事务中进行提交或者回滚。\n" +
                "如果封装事务存在,并且外层事务抛出异常回滚,那么内层事务必须回滚,反之,内层事务并不影响外层事务。\n" +
                "如果封装事务不存在,则同PROPAGATION_REQUIRED的一样\n" +
                "\n");
    }



    @Transactional(propagation = Propagation.NESTED)
    public void testTransactionNestedWithException() {
        User user = new User();
        user.setName("hlx");
        user.setRemark("hlx-内层事务回滚。外层事务不回滚!!!");
        userMapper.updateByPrimaryKeySelective(user);
        System.out.println("我就是测试事务传播行为PROPAGATION_NESTED抛出异常的");
        System.out.println("表示如果当前方法正有一个事务在运行中,则该方法应该运行在一个嵌套事务中,\n" +
                "被嵌套的事务可以独立于被封装的事务中进行提交或者回滚。\n" +
                "如果封装事务存在,并且外层事务抛出异常回滚,那么内层事务必须回滚,反之,内层事务并不影响外层事务。\n" +
                "如果封装事务不存在,则同PROPAGATION_REQUIRED的一样\n" +
                "\n");
        throw new BaseException("-1", "内层事务抛出异常");
    }


    @Transactional(propagation = Propagation.NEVER)
    public void testTransactionNever() {
        System.out.println("我就是测试事务传播行为PROPAGATION_NEVER的");
        System.out.println("表示当方法不应该在一个事务中运行,如果存在一个事务,则抛出异常\n" +
                "\n");
    }


    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void testTransactionRequiredNew() {
        System.out.println("我就是测试事务传播行为PROPAGATION_REQUIRES_NEW的");
        System.out.println("表示当前方法必须运行在它自己的事务中。一个新的事务将启动,而且如果有一个现有的事务在运行的话,则这个方法将在运行期被挂起,直到新的事务提交或者回滚才恢复执行。\n" +
                "\n");
    }


    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void testTransactionNotSupported() {
        System.out.println("我就是测试事务传播行为PROPAGATION_NOT_SUPPORTED的");
        System.out.println("表示该方法不应该在一个事务中运行。\n" +
                "如果有一个事务正在运行,事务将被挂起,直到当前方法执行完成才恢复执行\n" +
                "\n");
        System.out.println("睡眠5s");
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("睡醒了");
    }
}
版权声明:如果没有实践过,请不要转载,容易害人,转载请注明出处,禁止用于商业用途(http://blog.csdn.net/u013076044) https://blog.csdn.net/u013076044/article/details/79950916

Spring的7种事务传播行为类型

1、PROPAGATION_REQUIRED :如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。 2、PROPAGATION_SUPPORTS:支持当前事务,...
  • hsgao_water
  • hsgao_water
  • 2016-10-19 16:50:34
  • 8258

Spring中事务传播行为种类

Spring在TransactionDefinition接口中规定了7种类型的事务传播行为, 它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播: 事务传播行为类型 ...
  • huaishuming
  • huaishuming
  • 2015-09-16 12:28:43
  • 1283

浅析Spring 事务(二十一) spring事务的传播行为

经过我们上面一个章节的初步了解,我们已经知道了Spring事务的基本配置,今天我们一起接着讨论一下spring事务的传播...
  • linuu
  • linuu
  • 2016-03-29 16:07:34
  • 3831

spring 事务传播行为实例分析

欢迎转载和指正,转载时请说明来源
  • pml18710973036
  • pml18710973036
  • 2017-02-28 17:29:38
  • 6504

【Spring学习34】Spring事务(4):事务属性之7种传播行为

事务传播行为什么叫事务传播行为?听起来挺高端的,其实很简单。 即然是传播,那么至少有两个东西,才可以发生传播。单体不存在传播这个行为。事务传播行为(propagation behavior)指的就是...
  • soonfly
  • soonfly
  • 2017-04-20 21:35:42
  • 1145

浅析Spring事务传播行为和隔离级别

7个传播行为,4个隔离级别。 Spring事务的传播行为和隔离级别[transaction behavior and isolated level] Spring中事务的定义: Propagation...
  • it_wangxiangpan
  • it_wangxiangpan
  • 2014-04-20 13:23:41
  • 15677

spring事务(Transaction)的七种事务传播行为及五种隔离级别

spring事务(Transaction)的七种事务传播行为及五种隔离级别
  • baidu_37107022
  • baidu_37107022
  • 2017-07-20 21:25:11
  • 1312

Spring声明式事务@Transactional传播行为

在@Transactional注解中,可以propagation属性用来配置事务传播,支持7种不同的传播机制: REQUIRED:业务方法需要在一个事务中运行,如果方法运行时,已处在一个事务中,那么就...
  • totally123
  • totally123
  • 2016-08-24 16:20:06
  • 1949

spring 事务传播行为和事务隔离级别

1、Spring声明式事务 声明式事务(declarative transaction management)是Spring提供的对程序事务管理的方式之一。 Spring的声明式事务顾...
  • yujin753
  • yujin753
  • 2014-12-29 20:30:56
  • 3015

Spring事务的传播行为 @Transactional

Spring事务的传播行为   在service类前加上@Transactional,声明这个service所有方法需要事务管理。每一个业务方法开始时都会打开一个事务。 Spring默认情况下会...
  • seng3018
  • seng3018
  • 2011-08-16 09:21:45
  • 13931
收藏助手
不良信息举报
您举报文章:Spring 事务传播行为-其中类型功能测试
举报原因:
原因补充:

(最多只允许输入30个字)