阶段一-01.万丈高楼,地基首要-第2章 单体架构设计与准备工作-2-24 详解事务的传播-1

面试题:spring里面事务的传播有哪几种,分别是怎样的

点进来看@Transactional的源码



在使用这个注解的时候,其实是有一个默认的值 的。表示当前是一定要使用事务。如果当前的事物没有或者不存在,那么会自己新创建一个事务。如果当前方法本身存在事务,那么就不需要再额外的创建一个事务。它会额外的加入现有的事务里面去。

Propagation是一个枚举类

Ctrl+F12就可以把当前类里面的方法内容以列表的形式展示出来。让我们进行快速的浏览。

记得要在StuService的接口内定义这些方法

  public void saveParent();
    
    public void saveChildren();

    public void saveChild1();

    public void saveChild2();

 


新增加的结果方法用于测试

 

 public void saveParent() {
        Stu stu=new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }
//    @Transactional(propagation = Propagation.REQUIRED)
    public void saveChildren() {
       saveChild1();
       int a=1/0;
       saveChild2();
    }

    public void saveChild1() {
        Stu stu1=new Stu();
        stu1.setName("child-1");
        stu1.setAge(11);
        stuMapper.insert(stu1);
    }
    public void saveChild2() {
        Stu stu1=new Stu();
        stu1.setName("child-2");
        stu1.setAge(22);
        stuMapper.insert(stu1);
    }

 



创建了另外的service:TestTransService

package com.imooc.service;

public interface TestTransService {
    public void testPropagationTrans();
}

 

创建实现类:注入stuService

这个service主要是调用保存的方法。


这里有个注释,事务传播一共有7个

我们先来讲第一个Required


在api项目里面加入了Junit的依赖。我们在api工程里面使用Junit框架来做测试。

新建test类

加上注解。@RunWith和@SpringBootTet。在加这两个注解的时候,如果提示找不到,那么就注意maven查看是否下载了对应的jar包。maven install也可以试试

 

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class TransTest {
    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransService testTransService;

    @Test
    public void myTest() {
        testTransService.testPropagationTrans();
    }
}

 


无事务的情况


全部都不写事务,会出现的问题。在saveChildren故意报错。


数据库内现在一条数据都没有。保证数据库是空的。

运行测试类。




运行后。报错了。

父方法和子方法成功保存到数据库内。

开启事物

父方法开启事务

@Transactional(propagation = Propagation.REQUIRED)


子方法内saveChildren还是故意留有错误。


数据库内数据清空

运行测试类

 
数据库内没有数据。事务起了作用,全部回滚了。


这是因为父方法这里进行了事物的传播。

在子方法里面虽然没有增加@Transactional的注解。

但是事物会传递到下一个方法里面的

当我们的子方法内出现异常以后。两个方法里面的事物都会回滚。

开启子方法的事务

父方法事务关闭,子方法(报错的那个方法)事务开启。


父方法的事务注释掉。


运行测试。父方法成功保存了。父级别方法并没有事物,子方法的保存被回滚了。

开启父方法事物,子方法也开启


子方法的事物也是开启的

数据库内清空

运行测试类

依然报错

数据库依然没有数据

required总结

required:使用当前事务,如果当前没有事务,则自己创建一个屋,子方法是必须运行在一个事务中的;如果当前存在事务,则加入这个事务成为一个整体。


父方法有事务的话会传递给子方法。父方法没有事务,子方法有事务,会执行子方法的事务。

required多用于增删改的操作。

supports

从字面上看是一种支持。主要是用于做查询的。

父方法事务先注释掉

子方法的事务改为supports:@Transactional(propagation = Propagation.SUPPORTS)


清空数据库,运行测试类。

事务没作用。



子方法用了supports。外层方法并没有事务,它就不使用事务,它是跟着外层走的
如果说外层使用了required。子方法还是supports


清空数据库,运行测试。---》数据库为空。事务进行了回滚。

supports总结

主要用于查询。

SUPPORT:当前有事务,则使用事务,如果当前没有事务,则不使用事务


required和supports是两个最常用的

Mandatory

首先看它的注释。它是支持当前的事物的,如果不存在事物就会抛出异常,它强制了谁调用了我 ,谁就必须要有事物。它没有事务就会抛出异常。

把父方法的事物注释掉。

被调用方,也就是子方法使用mandatory

运行测试



报错信息,没有找到事务。

父方法的事物开启

运行测试,没有报Mandatory抛出的异常。这个错误是我自己代码的抛出异常。

mandatory总结

前方这个方法的方法里面,必须要带着事务,如果不带这事务。那么自己就会抛出异常。

改传播属性强制必须存在一个事务,如果不存在则抛出异常

 

总结:

 Required:
父方法内事务开启。那么子方法内,只要报错都会回滚
@Transactional(propagation = Propagation.REQUIRED)

父方法事务不开,只开启报错的方法的事物,那么父方法先执行的没有错误的方法可以顺利执行


required:使用当前事务,如果当前没有事务,则自己创建一个屋,子方法是必须运行在一个事务中的;如果当前存在事务,则加入这个事务成为一个整体。
required多用于增删改的操作。
*************************************************
@Transactional(propagation = Propagation.SUPPORTS)
supports:从字面上看是一种支持。主要是用于做查询的。

子方法用了supports。外层方法并没有事务,它就不使用事务,它是跟着外层走的
如果说外层使用了required。子方法还是supports
SUPPORT:当前有事务,则使用事务,如果当前没有事务,则不使用事务

***********************************************
mandatory:
改传播属性强制必须存在一个事务,如果不存在则抛出异常

 

结束

posted @ 2019-12-16 00:25  高山-景行  阅读(270)  评论(0编辑  收藏  举报