Java事务认识整理(更新中)

一、什么是事务

       事务(Transaction)是并发控制单位,是用户定义的一个操作序列,这些操作要么都做,要么都不做,是一个不可分割的工作单位。

二、事务的传播
1. 不使用事务
(1)创建StuService 类
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

    public void saveChildren(){
        saveChildren1();
        int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();

    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,会调用StuService 类的saveChildren方法,当执行到1/0时提示报错,此时数据库的结果如下所示。成功保存了parent和child-1的数据。
在这里插入图片描述

2. 开启事务 REQUIRED
场景一:父方法开启REQUIRED事务,子方法不开启事务
(1)创建StuService 类
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

    public void saveChildren(){
        saveChildren1();
        int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类(此处开启事务REQUIRED)
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();

    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,会调用StuService 类的saveChildren方法,同样的,当执行到1/0时提示报错,此时数据库的结果如下所示。此时数据库中没有保存任何数据。这是因为作为父方法的testPropagationTrans上面我们此时加上了 @Transactional(propagation = Propagation.REQUIRED)注解,它是有事务的。虽然在该方法调用的调用的两个子方法上面没有添加事务的注解,但是父方法此时添加的这个REQUIRED事务会传递到调用的子方法上。所以,当saveChildren()方法发生异常以后,整个父方法及其所调用的方法都会发生回滚。
在这里插入图片描述

场景二:父方法不开启事务,子方法开启事务
(1)创建StuService 类(此处开启事务REQUIRED)
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

	@Transactional(propagation = Propagation.REQUIRED)
    public void saveChildren(){
        saveChildren1();
        int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类(此处开启事务REQUIRED)
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();

    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,会调用StuService 类的saveChildren方法,同样的,当执行到1/0时提示报错,此时数据库的结果如下所示。正如最开始所说的,如果当前所在的整个方法体里面,它本身就不带有事务的话,它会重新的去创建一个事务的。也就是当前saveChildren()会存在于一个事务中,而saveParent()不存在事务,所以此时成功保存了parent的数据至数据库。
在这里插入图片描述

3. 开启事务 SUPPORTS

       当父方法和子方法同时开启事务时,子方法即与父方法存在于同一个事务中,即子方法此时带有事务,所以它不会去创建自己的事务。此时结果与场景一相同,此处不做演示。

(1)创建StuService 类(此处开启事务SUPPORTS)
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

	@Transactional(propagation = Propagation.SUPPORTS)
    public void saveChildren(){
        saveChildren1();
        int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();

    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,会调用StuService 类的saveChildren方法,同样的,当执行到1/0时提示报错,此时数据库的结果如下所示。因为父方法testPropagationTrans()没有使用事务,而子方法saveChildren()使用SUPPORTS事务时,会跟着父方法。如果父方法没有事务,则子方法没有事务;如果父方法有事务,则子方法就有事务。
       如果在这个例子的基础上,给testPropagationTrans()方法加上@Transactional(propagation = Propagation.REQUIRED)注解,则数据库将不会保存任何数据。

在这里插入图片描述

4. 开启事务 MANDATORY
(1)创建StuService 类(此处开启事务MANDATORY)
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

	@Transactional(propagation = Propagation.SUPPORTS)
    public void saveChildren(){
        saveChildren1();
        int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();

    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,会调用StuService 类的saveChildren方法。此时会报IllegalTransactionStateException: No existing transaction found for transaction marked with propagation ‘mandatory’。
在这里插入图片描述
       当使用MANDATORY事务注解时,如果父方法(即调用方)不存在事务的话,会抛出一个异常,该注解会强制要求调用方必须存在事务。在该例子的基础上,给testPropagationTrans()方法加上@Transactional(propagation = Propagation.REQUIRED)注解。运行测试方法时,就不会再报IllegalTransactionStateException异常。运行结果将与事务 REQUIRED场景一相同。

5 开启事务 REQUIRES_NEW
场景一:
(1)创建StuService 类(此处开启事务REQUIRES_NEW)
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

	@Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveChildren(){
        saveChildren1();
        int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    //@Transactional(propagation = Propagation.REQUIRED)
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();

    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,会调用StuService 类的saveChildren方法,同样的,当执行到1/0时提示报错,此时数据库的结果如下所示。可以看到,数据库这个时候成功保存了一条记录。这条记录就是在父方法(调用方)testPropagationTrans()中在调用saveParent()的时候所保存的。而另一个被调用的saveChildren()方法因为开启了事务REQUIRES_NEW,所以saveChildren()方法会生成改方法的事务,并且与saveParent()方法是分开的,当saveChildren()发生异常时,它自己发生了回滚。
在这里插入图片描述

场景二:
(1)创建StuService 类(此处开启事务REQUIRES_NEW)
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

	@Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveChildren(){
        saveChildren1();
        int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类(开启事务REQUIRED)
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();

    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,会调用StuService 类的saveChildren方法,同样的,当执行到1/0时提示报错,此时数据库的结果如下所示。数据库没有保存任何记录。在这个过程中,saveChildren()方法是另外的一个新的事务,它报错后会将异常给到父方法testPropagationTrans(),而父方法中调用了saveParent(),所以父方法的事务会使saveParent()进行回滚。
在这里插入图片描述

场景三:
(1)创建StuService 类(此处开启事务REQUIRES_NEW,并将异常语句int a = 1/0;注释)
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

	@Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveChildren(){
        saveChildren1();
        //int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类(开启事务REQUIRED,并增加异常语句int a = 1/0;)
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();
		int a = 1/0;
    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,会调用StuService 类的saveChildren()方法,此时saveChildren()方法是没有异常的。此时执行结果如下,成功保存了两条child数据。虽然父方法此时开启了事务REQUIRED,但是子方法开启了新事物REQUIRES_NEW,所以父方法中的异常不会影响子方法saveChildren()的异常。
在这里插入图片描述

6 开启事务 NOT_SUPPORTS
场景一:
(1)创建StuService 类(此处开启事务NOT_SUPPORTS)
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

	@Transactional(propagation = Propagation.NOT_SUPPORTS)
    public void saveChildren(){
        saveChildren1();
        int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    //@Transactional(propagation = Propagation.REQUIRED)
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();
	
    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,会调用StuService 类的saveChildren()方法,当执行到1/0时提示报错,此时数据库的结果如下所示。首先,父方法testPropagationTrans()没有事务,而且子方法saveChildren()开启NOT_SUPPORTS后,它本身也就没有事务,所以,此时尽管子方法报异常,它也能成功保存child-1的数据。
在这里插入图片描述

场景二:
(1)创建StuService 类(此处开启事务NOT_SUPPORTS)
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

	@Transactional(propagation = Propagation.NOT_SUPPORTS)
    public void saveChildren(){
        saveChildren1();
        int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类(开启事务REQUIRED)
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();
	
    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,会调用StuService 类的saveChildren()方法,当执行到1/0时提示报错,此时数据库的结果如下所示。因为此时子方法不支持事务,所以child-1没有被回滚;而父方法此时是有事务的,所以会回滚parent数据而没有被保存。
在这里插入图片描述

7 开启事务 NERVER
(1)创建StuService 类(此处开启事务NERVER)
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

	@Transactional(propagation = Propagation.NERVER)
    public void saveChildren(){
        saveChildren1();
        int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类(开启事务REQUIRED)
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();
	
    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,此时会直接报异常IllegalTransactionStateException: Existing transaction found for transaction maeked with propagation ‘never’ 。此时不会执行方法,也就不会有任何数据的保存或者回滚。
       如果此时把父方法testPropagationTrans()的事务去掉,重新执行测试方法。数据库中保存的数据如下。
在这里插入图片描述

7 开启事务 NESTED
(1)创建StuService 类(此处开启事务NESTED,注释掉异常语句int a = 1/0;)
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveParent(){
        Stu stu = new Stu();
        stu.setName("parent");
        stu.setAge(19);
        stuMapper.insert(stu);
    }

	@Transactional(propagation = Propagation.NESTED)
    public void saveChildren(){
        saveChildren1();
        //int a = 1/0;
        saveChildren2();
    }

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

    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);
    }
}
(2)创建TestTransServiceImpl 类(开启事务REQUIRED,增加异常语句int a = 1/0;)
@Service
public class TestTransServiceImpl {

    @Autowired
    private StuService stuService;
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void testPropagationTrans(){

        stuService.saveParent();

        stuService.saveChildren();
		int a = 1/0;
    }
}

(3)创建测试类TransTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    private StuService stuService;

    @Autowired
    private TestTransServiceImpl testTransService;

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

       直接执行测试类的方法,此时会直接报异常IllegalTransactionStateException: Existing transaction found for transaction maeked with propagation ‘never’ 。此时不会执行方法,也就不会有任何数据的保存或者回滚。
       如果此时把父方法testPropagationTrans()的事务去掉,重新执行测试方法。数据库中保存的数据如下。

小结

  • REQUIRED
           使用当前的事务,如果当前没有事务,则自己新建一个事务,子方法是必须运行在一个事务中的;如果当前存在事务,则加入这个事务,成为一个整体。在事务的传播里面,默认的就是REQUIRED,而REQUIRED也是比较多的用于增删改这些操作,所以一般使用REQUIRED就可以了。
           举例:领导没饭吃,小明有钱,小明会自己买了自己吃;领导有的吃,会分给小明一起吃。

  • SUPPORTS
           如果当前有事务,则使用事务;如果当前没有事务,则不适用事务。(对于支持类型的事务,主要用于去做查询。)
           举例:领导没饭吃,小明也没饭吃;领导有饭吃,小明也有饭吃。

  • MANDATORY
           该传播属性强制必须存在一个事务,如果不存在,则抛出异常。
           举例:领导必须管饭,不管饭没饭吃,小明就不乐意了,就不干了(抛出异常)。

  • REQUIRES_NEW
           如果当前有事务,则挂起该事务,并且自己创建一个新的事务给自己使用;如果当前没有事务,则同REQUIRED。
           领导有饭吃,小明偏不要,小明自己买了自己吃。

  • NOT_SUPPORTS
           如果当前有事务,则把事务挂起,自己不使用事务去运行数据库操作。

  • NEVER
           如果当前有事务存在,则抛出异常。

  • NESTED
           如果当前有事务,则开启子事务(嵌套事务),嵌套事务时独立提交或者回滚的;如果当前没有事务,则同REQUIRED。但是如果主事务提交,则会携带子事务一起提交。如果主事务回滚,子事务会一起回滚。相反,子事务异常,则父事务可以回滚或不回滚。

三、Transaction注解事务失效场景
场景一:

       在有的博客中这样说到:如果在同一个类中,a方法调用了b方法,然后事务注解只添加在b方法上,当调用a方法时,b方法的事务是不生效的。
       以下是验证该说法的例子

(1)创建测试StuServiceImpl类
@Service
public class StuServiceImpl implements StuService {

    @Autowired
    private StuMapper stuMapper;

    public void saveChildren(){
        saveChildren1();
        saveChildren2();
    }

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

    @Transactional(propagation = Propagation.REQUIRED)
    public void saveChildren2(){
        Stu stu2 = new Stu();
        stu2.setName("child-2");
        stu2.setAge(22);
        stuMapper.insert(stu2);

        int a = 1/0;

        Stu stu3 = new Stu();
        stu3.setName("child-3");
        stu3.setAge(33);
        stuMapper.insert(stu3);
    }
}
(2)创建测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class TransTest {

    @Autowired
    private StuService stuService;

    @Test
    public void myTest2(){
        stuService.saveChildren();
    }

}

       运行结果如下所示。
在这里插入图片描述
       从运行结果结果中,我们可以看出加在saveChildren2()方法上的事务注解没有生效,它在执行插入child-2后,再执行int a = 1/0时抛出异常,如果事务生效则child-2应该会被回滚。
       如果我们把saveChildren2()方法上的事务注解去掉,并在saveChildren()方法上加事务注解。清空数据库表并重新执行测试方法,此时事务生效并回滚saveChildren()插入的数据,则执行结果如下:
图1

  • 事务失效原因
四、Transaction注解事务实现原理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值