
进入 Transactional 注解,默认使用的属性是 REQUIRED,表示当前方法是一定要使用事务,如果当前事务不存在,则创建新的事务,如果当前方法本身有事务,则不创建新的事务。
Propagation 一共有七个属性
下面通过示例详细介绍七个属性的作用
foodie-dev-service 中 StuService 接口添加两个方法
package com.imooc.service;import com.imooc.pojo.Stu;/*** @author 92578* @since 1.0*/public interface StuService {public Stu getStuInfo(int id);public void saveStu();public void updateStu(int id);public void deleteStu(int id);public void saveParent();public void saveChildren();}
foodie-dev-service 中 StuServiceImpl 实现对应的方法
package com.imooc.service.impl;import com.imooc.mapper.StuMapper;import com.imooc.pojo.Stu;import com.imooc.service.StuService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;/*** @author 92578* @since 1.0*/@Servicepublic class StuServiceImpl implements StuService {@Autowiredprivate StuMapper stuMapper;@Transactional(propagation = Propagation.SUPPORTS)@Overridepublic Stu getStuInfo(int id) {return stuMapper.selectByPrimaryKey(id);}@Transactional(propagation = Propagation.REQUIRED)@Overridepublic void saveStu() {Stu stu = new Stu();stu.setName("jack");stu.setAge(19);stuMapper.insert(stu);}@Transactional(propagation = Propagation.REQUIRED)@Overridepublic void updateStu(int id) {Stu stu = new Stu();stu.setId(id);stu.setName("lucy");stu.setAge(20);stuMapper.updateByPrimaryKey(stu);}@Transactional(propagation = Propagation.REQUIRED)@Overridepublic void deleteStu(int id) {stuMapper.deleteByPrimaryKey(id);}// 测试事务 required 属性@Overridepublic void saveParent() {Stu stu = new Stu();stu.setName("parent");stu.setAge(19);stuMapper.insert(stu);}@Overridepublic void saveChildren() {saveChild1();int a = 1 / 0;saveChild2();}public void saveChild1() {Stu stu = new Stu();stu.setName("child-1");stu.setAge(11);stuMapper.insert(stu);}public void saveChild2() {Stu stu = new Stu();stu.setName("child-2");stu.setAge(22);stuMapper.insert(stu);}}
foodie-dev-service 中 创建 TestTransService 接口
package com.imooc.service;
public interface TestTransService {
public void testPropagationTrans();
}
foodie-dev-service 中 创建 TestTransServiceImpl 实现类
package com.imooc.service.impl;
import com.imooc.service.StuService;
import com.imooc.service.TestTransService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Created by 92578 on 2020/8/15 0:49
**/
@Service
public class TestTransServiceImpl implements TestTransService {
@Autowired
private StuService stuService;
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
在 foodie-dev-api 的 pom 中添加 JUnit 包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
在 foodie-dev-api 的 src/test/java/com/test 包下创建 TransTest 类
package com.test;
import com.imooc.Application;
import com.imooc.service.StuService;
import com.imooc.service.TestTransService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Created by 92578 on 2020/8/15 1:10
**/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class TransTest {
@Autowired
public StuService stuService;
@Autowired
private TestTransService testTransService;
@Test
public void myTest() {
testTransService.testPropagationTrans();
}
}
确保 Stu 表中没有数据
运行测试后提示出错
数据库中插入了两条记录
2.20.1 Propagation.REQUIRED
在 TestTransServiceImpl 类中的 testPropagationTrans 方法启用事务
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
清除原有数据,重新运行测试方法,发现表中没有再插入数据
通过上面示例可以发现,事务会进行传播,我们在测试的父方法上面开启事务,调用的子方法 saveParent 和 saveChildren 虽然没有添加事务,但是事务会传递到子方法中。
在 StuServiceImpl 类中的 saveChildren 方法上添加事务
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void saveChildren() {
saveChild1();
int a = 1 / 0;
saveChild2();
}
在 TestTransServiceImpl 类中的 testPropagationTrans 方法关闭事务
// @Transactional(propagation = Propagation.REQUIRED)
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
重新运行测试方法,发现数据库中插入一条记录
由于父级方法并没有事务,因此 saveParent 方法执行后会保存到数据库中,saveChildren 方法开启了事务,因此进行回滚
【总结】
Propagation.REQUIRED:使用当前的事务,如果当前没有事务,则自己新建一个事务,子方法是必须运行在一个事务中的;如果当前存在事务,则加入这个事务,成为一个整体。(适用于增加、修改、删除)
举例:领导没饭吃,我有钱,我会自己买了自己吃;领导有的吃,会分给你一起吃。
2.20.2 Propagation.SUPPORTS
在 StuServiceImpl 类中的 saveChildren 方法上添加事务
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public void saveChildren() {
saveChild1();
int a = 1 / 0;
saveChild2();
}
清空数据,执行测试方法,发现数据库中插入两条记录
在 TestTransServiceImpl 类中的 testPropagationTrans 方法启用事务
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
清空数据,执行测试方法,发现数据库中没有记录
【总结】
Propagation.SUPPORTS:如果当前有事务,则使用事务;如果当前没有事务,则不使用事务。(适用于查询)
举例:领导没饭吃,我也没饭吃;领导有饭吃,我也有饭吃。
2.20.3 Propagation.MANDATORY

在 TestTransServiceImpl 类中的 testPropagationTrans 方法关闭事务
// @Transactional(propagation = Propagation.REQUIRED)
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
在 StuServiceImpl 类中的 saveChildren 方法上添加事务
@Transactional(propagation = Propagation.MANDATORY)
@Override
public void saveChildren() {
saveChild1();
int a = 1 / 0;
saveChild2();
}
执行测试方法,提示出错,没有找到一个存在的事务
在 TestTransServiceImpl 类中的 testPropagationTrans 方法启用事务
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
执行测试方法,提示出错
【总结】
Propagation.MANDATORY:该传播属性强制必须存在一个事务,如果不存在,则抛出异常。
举例:领导必须管饭,不管饭没饭吃,我就不乐意了,就不干了(抛出异常)
