一、Spring中七种事务传播行为
事务传播行为类型 | 说明 |
---|---|
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
二、准备工作
创建两张表,学生表和教师表
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`age` int(11) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创建对应实体类,mapper,以及service。
@Data
@TableName("student")
@Accessors(chain = true)
public class Student {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField(value = "age")
private Long age;
@TableField(value = "name")
private String name;
}
@Data
@TableName("teacher")
@Accessors(chain = true)
public class Teacher {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField(value = "name")
private String name;
}
@Mapper
public interface StudentMapper extends BaseMapper<Student> {
}
@Mapper
public interface TeacherMapper extends BaseMapper<Teacher> {
}
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
public void addTeacher() {
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
public void addStudent() {
studentMapper.insert(new Student().setName("小明"));
}
}
三、各种传播行为模拟
模拟一个事务(插入一条教师记录,一条学生记录),此外,每次经过测试之后,都会清空数据库对应的表记录。
1、没有事务支持
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
public void addTeacher() {
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
public void addStudent() {
studentMapper.insert(new Student().setName("小明"));
throw new RuntimeException("业务异常");
}
}
可以看到,没有事务的支持,因为没有事务的支持,即使在最后抛出的异常,数据依然是正常入库了。
2、PROPAGATION_REQUIRED
propagation(n.传播;扩展;宣传;培养)
required(v 需要;(尤指根据法规)规定;使做(某事);使拥有(某物);依赖;依靠 ;adj 必修的)
顾英文名思意,就需要传播。这种传播机制也是我们工作中用的最多的。
2.1 场景一: 外层方法增加事务,内层方法不加
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
throw new RuntimeException("业务异常");
}
}
数据库结果
控制台打印结果
可以看到事务生效,异常导致前面插入的两条记录都回滚掉了,并且addStudent()加入了外层addTeacher()的事务,打印了相同的事务名。
2.2 场景二: 外层方法不加事务,内层方法加
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
throw new RuntimeException("业务异常");
}
}
数据库结果
控制台打印结果
可以看到,在外层方法addTeacher()没有事务的时候,内层方法addStudent()自己新建一个事务,所以内层方法因为异常回滚导致学生记录回滚掉了,而外层方法因为没有事务支持,即使报错了,教师记录还是新增成功了。
2.3 场景三: 外内层公用一个事务,且内层异常捕获掉。
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
try {
throw new RuntimeException("业务异常");
} catch (RuntimeException e) {
}
}
}
数据库结果
控制台打印结果
可以看到这种情况下,内外层方法都是有事务控制的,而异常被捕获,相当一段正常的代码,所以学生和教师两条记录都插入成功了。
而即使把捕获异常的那段代码丢到外层方法,实现的效果也是一样的。
3、PROPAGATION_SUPPORTS
3.1 场景一: 外层方法有事务
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
try {
throw new RuntimeException("业务异常");
} catch (RuntimeException e) {
}
}
}
控制台打印结果
可以看到,这时候内层事务加入到了外层事务,这种情况和required是一致的。
3.2 场景二: 外层方法没有事务
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
throw new RuntimeException("业务异常");
}
}
数据库结果
控制台打印结果
可以看到虽然内层方法打印了事务名,但这时候是没有事务支持的,导致学生和教师的记录即使在有异常抛出的情况下也插入成功了。
4、PROPAGATION_MANDATORY
mandatory adj.强制性的;强制的;法定的;义务的 /ˈmændətəri/ 来,跟我一起读,忙得特瑞,欸,好。很强硬,必要要有事务,没有就罢工。
4.1 场景一: 外层方法有事务
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
@Transactional(propagation = Propagation.MANDATORY)
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
throw new RuntimeException("业务异常");
}
}
数据库结果
控制台打印结果
可以看到,这种情况和
可以看到,这时候内层事务加入到了外层事务,这种情况和required和SUPPORTS 是一致的。
4.2 场景二: 外层方法没有事务
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
@Transactional(propagation = Propagation.MANDATORY)
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
throw new RuntimeException("业务异常");
}
}
控制台打印结果
可以看到,因为外层没有事务,走到内层方法得时候抛出非法的事务状态异常。
5、PROPAGATION_REQUIRES_NEW
REQUIRES_NEW 需要一个新的,不管外层方法咋样,内层都需要一个新的。
5.1 场景一: 外层方法有事务
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
throw new RuntimeException("业务异常");
}
}
控制台打印结果
可以看到,内外层方法是由不同的事务支持,但这时候数据库都没有插入成功,因为内层异常导致内层数据回滚,然后异常又抛到外层,导致外层数据回滚。
那这时候又有聪明的同学问了,欸,有没有什么办法让内层回滚,外层数据正常插入了呢,当然可以,外层捕获异常就可以了,代码如下
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
try {
studentService.addStudent();
} catch (Exception e) {
}
}
这种一般用于某些业务的日志记录场景,外层事务就可以在try和catch两个地方记录操作成功的日志和操作失败的日志。
5.1 场景二: 外层方法没有事务
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
throw new RuntimeException("业务异常");
}
}
数据库结果
控制台打印结果
这种情况是required没有外层事务时是一样的
,内层自己新建事务,所以异常导致内层数据回滚,而外层没有事务导致数据插入成功。
6、PROPAGATION_NOT_SUPPORTED
NOT_SUPPORTED 不支持事务,外层没有事务,挺好,内层我也不要;外层有事务,我不理解,但是我不接受,内层将外层事务挂起,内层以非事务执行。
6.1 场景一: 外层方法有事务
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
throw new RuntimeException("业务异常");
}
}
数据库结果
控制台打印结果
这种情况下,内层方法将外层事务挂起,不走事务
,所以内层记录插入成功,而外层方法由于内层的异常导致记录回滚。
6.1 场景二: 外层方法没有事务
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
throw new RuntimeException("业务异常");
}
}
数据库结果
控制台打印结果
可以看到,这时候内外层都没有事务支持
,所以即使异常抛出了,但由于是在最后面抛出的,所以两条记录都插入成功了。
7、PROPAGATION_NEVER
NEVER adv. 从不;从未;绝不
绝不,休想,我绝不可能爱你(I can never love you),
你休想(Never on your life)
外层有事务,内层支持抛出异常,都别活了!好好好,可以不爱,请别伤害哇。
@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {
private final TeacherMapper teacherMapper;
private final StudentService studentService;
public TeacherServiceImpl(TeacherMapper teacherMapper, StudentService studentService) {
this.teacherMapper = teacherMapper;
this.studentService = studentService;
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addTeacher() {
log.info("新增教师方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增教师方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
teacherMapper.insert(new Teacher().setName("周老师"));
studentService.addStudent();
}
}
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
private final StudentMapper studentMapper;
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
@Transactional(propagation = Propagation.NEVER)
public void addStudent() {
log.info("新增学生方法是否存在事务{}", TransactionSynchronizationManager.isActualTransactionActive());
log.info("新增学生方法事务名称为{}", TransactionSynchronizationManager.getCurrentTransactionName());
studentMapper.insert(new Student().setName("小明"));
throw new RuntimeException("业务异常");
}
}
控制台打印结果
可以看到,因为外层有事务,走到内层方法得时候抛出非法的事务状态异常。
8、PROPAGATION_NESTED
NESTED abbr.嵌套的;
PROPAGATION_NESTED 开始一个 "嵌套的" 事务, 它是已经存在事务的一个真正的子事务. 潜套事务开始执行时, 它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 嵌套事务是外部事务的一部分, 只有外部事务结束后它才会被提交。 由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于, PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 嵌套事务也会被 commit, 这个规则同样适用于 roll back。
四、总结
- PROPAGATION_REQUIRED 就是需要,有就加入,没有就新建一个。
- PROPAGATION_SUPPORTS 支持你,支持外层,外层有,俺也有,外层没有,俺也不要了
- PROPAGATION_MANDATORY 很强硬的,外层你有,大家就好好的,你没有,都别活了,我要抛异常!
- PROPAGATION_REQUIRES_NEW 内层方法:你外层爱咋咋地,我自己新建一个事务
- PROPAGATION_NOT_SUPPORTED 不支持,不管外层有没有,我都以非事务执行,比较温和,你有我就把你挂起
- PROPAGATION_NEVER 又来一个强硬的主儿,不允许外层有事务,休想!
- PROPAGATION_NESTED 嵌套事务,成为外层的一个子事务。