通过枚举类查询所有的事务传播类型,
Spring 定义了一个事务传播的枚举类:Propagation
public enum Propagation {
// 常用于增删改
// 调用方有事务,被调用方也有事务,则被调用方加入调用方共用一个事务
// 也是事务注解默认的使用方式
REQUIRED(0),
// 常用于查询。
// 事务的传播方式是跟着外层方法走的,如果外层没有事务,则不使用事务
SUPPORTS(1),
// 强制的,谁调用了我,调用方就必须要有一个事务,如果没有事务就抛出异常
MANDATORY(2),
// 调用方有事务,则挂起该事务,并且创建一个新的事务给自己使用;
// 调用方没有事务,则同REQUIRED
REQUIRES_NEW(3),
// 如果调用方有事务则把事务挂起,自己不使用事务去运行数据库操作
// 常用查询操作
NOT_SUPPORTED(4),
// 以没有事务的形式去执行,如果发现调用方有事务存在则抛出异常
NEVER(5),
// 调用方有事务,开启嵌套事务,否则同REQUIRED
NESTED(6);
private final int value;
private Propagation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
栗子:
//演示事务传播
// demo1 ,演示REQUIRED
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void testPropagationTrans() {
// 事务会往下传递,saveChildren方法里面发生异常后,saveParent(),saveChildren()都会回滚
// 数据库不会有任何数据插入成功
stuService.saveParent();
stuService.saveChildren();
}
// demo2,演示调用方没有事务,子方法有事务
@Override
public void testPropagationTrans() {
// saveParent会保存到数据库里面去,而saveChildren发生异常后会进行回滚,因为saveChildren使用了
// REQUIRED事务传播
stuService.saveParent();
stuService.saveChildren();
}
@Override
public void saveParent() {
Stu stu = new Stu();
stu.setName("parent");
stu.setAge(19);
stuMapper.insert(stu);
}
// 调用方没有事务,创建新的事务,saveChild1,saveChild2所处同一事务中,异常后都会回滚
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void saveChildren() {
saveChild1();
int a = 1 / 0;
saveChild2();
}
// demo3,演示SUPPORTS。子方法依靠外层方法的事务,外层有事务就使用,没有就不使用
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
// 子方法
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public void saveChildren() {
saveChild1();
int a = 1 / 0;
saveChild2();
}
// demo4,演示MANDATORY。强制的,调用方必须拥有事务否则报错
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
@Transactional(propagation = Propagation.MANDATORY)
@Override
public void saveChildren() {
saveChild1();
int a = 1 / 0;
saveChild2();
}
// 如果调用方没有事务,则会报错
org.springframework.transaction.IllegalTransactionStateException:
No existing transaction found for transaction marked with propagation 'mandatory'
//demo5 演示 REQUIRES_NEW 调用方没有事务的情况
@Override
public void testPropagationTrans() {
// saveChildren发生异常会进行回滚,而saveParent会保存成功
stuService.saveParent();
stuService.saveChildren();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void saveChildren() {
saveChild1();
int a = 1 / 0;
saveChild2();
}
// demo 6 ,演示REQUIRES_NEW 调用方有事务的情况,且调用方发生了异常
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void testPropagationTrans() {
// saveParent会回滚,saveChildren不会回滚
// 因为saveChildren的REQUIRES_NEW,会在父级方法有事务的时候,创建一个新的事务去使用
stuService.saveParent();
stuService.saveChildren();
int a = 1 / 0;
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void saveChildren() {
saveChild1();
//int a = 1 / 0;
saveChild2();
}
// demo 7 演示NOT_SUPPORTED
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void testPropagationTrans() {
// saveChildren抛出异常没有回滚,但是saveParent需要被回滚
stuService.saveParent();
stuService.saveChildren();
//int a = 1 / 0;
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@Override
public void saveChildren() {
saveChild1();
int a = 1 / 0;
saveChild2();
}
// demo 8 演示never
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void testPropagationTrans() {
// 会抛出异常,因为调用方拥有事务
stuService.saveParent();
stuService.saveChildren();
//int a = 1 / 0;
}
org.springframework.transaction.IllegalTransactionStateException:
Existing transaction found for transaction marked with propagation 'never'
// demo9 演示被调用方使用NESTED,调用方使用REQUIRED
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
// 调用方发生异常,那么saveChildren方法是跟着调用方一起回滚的
int a = 1 / 0;
}
@Transactional(propagation = Propagation.NESTED)
@Override
public void saveChildren() {
saveChild1();
// int a = 1 / 0;
saveChild2();
}
@Transactional 的使用注意事项总结
@Transactional注解只有作用到 public 方法上事务才生效- 底层使用的数据库必须支持事务机制,否则不生效。比如使用 MySQL ,innodb 引擎支持事务,myisam 引擎就不支持
- 一般常用的事务传播方式,查询使用SUPPORTS,增删改使用REQUIRED