spring 事务传播性
一.什么是事务传播性
大白话讲就是,方法之间互相调用的时候,事务如何传播,比如A()调用B(),B()的事务是和A()共用一个事务(失败一起提交)?
还是新事务(两者事务互不影响)?,还是说B()不需要事务?,这就是事务传播性的意思。
@Transactional()
public void methodA(){
methodB();
//doSomething
}
@Transactional()
public void methodB(){
//doSomething
}
代码中的methodB()默认的传播性是REQUIRED,表示和methodA共用一个事务,要提交一起提交,要失败一起回滚。
二.spring中几种事务传播性
| 事务传播性 | 说明 |
| REQUIRED | 默认传播性,如果当前有事务,就沿用当前事务,如果没有就新建一个事务 |
| SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务运行 |
| REQUIRES_NEW | 新建一个事务,如果当前存在事务,就把当前事务挂起 |
| NOT_SUPPORTED | 不支持事务,如果当前存在事务,就把当前事务挂起。 |
| MANDATORY | 强制使用当前事务,如果当前没有事务就抛异常 |
| NEVER | 以非事务方式运行,如果当前存在事务,则抛出异常 |
| NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
三.举例说明
1.REQUIRED
说明:支持当前事务,如果当前没有事务就新建一个事务
insertUser()和insertStu是共用一个事务,要提交一起提交要失败一起失败。
@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
User user = new User();
user.setName(name);
userDao.insertUser(user);
stuService.insertStu(name);
}
stuService中
@Transactional(propagation = Propagation.REQUIRED)
public void insertStu(String name){
Stu stu = new Stu();
stu.setName(name);
stuDao.insertUser(stu);
//这个地方发生异常,会引起insertStu也回滚,说明两者的事务是同一个
throw new RuntimeException();
}
2.REQUIRES_NEW
说明:开启新的事务,如果当前存在事务,就挂起当前事务。
insertUser()的失败回滚,不会导致insertStu的回滚,因为insertStu()在一个新的事务中。
@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
User user = new User();
user.setName(name);
userDao.insertUser(user);
stuService.insertStu(name);
throw new RuntimeException();
}
//上面的方法抛异常事务的回滚,不会导致下面事务回滚,stu插入成功,user插入失败
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insertStu(String name){
Stu stu = new Stu();
stu.setName(name);
stuDao.insertUser(stu);
}
3.SUPPORTS
说明:如果当前已经存在事务,那么加入该事务,否则创建一个所谓的空事务(可以认为无事务执行)
insertUser是以非事务运行的,所以insertStu也是没有事务的,所以两个保存都会成功
但是如果给inertStu加上@Transactional(propagation = Propagation.REQUIRED)insertStu是有事务的。
public void insertUser(String name) {
User user = new User();
user.setName(name);
userDao.insertUser(user);
stuService.insertStu(name);
throw new RuntimeException();
}
@Transactional(propagation = Propagation.SUPPORTS)
public void insertStu(String name){
Stu stu = new Stu();
stu.setName(name);
stuDao.insertUser(stu);
}
4.NOT_SUPPORTED
说明:不支持事务,如果当前存在事务,挂起当前事务,然后新的方法在没有事务的环境中执行
下面的insertUser会回滚,insertStu将以非事务运行,所以不会回滚
这种的业务场景可能是,日志写入事务要和主事务隔离,外层事务写入失败,不影响日志的写入。
@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
User user = new User();
user.setName(name);
userDao.insertUser(user);
stuService.insertStu(name);
throw new RuntimeException();
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void insertStu(String name){
Stu stu = new Stu();
stu.setName(name);
stuDao.insertUser(stu);
}
5.MANDATORY
说明:当前必须存在一个事务,否则抛出异常。
因为insertUser()没有配置事务,所以insertStu()会报错。
异常信息:No existing transaction found for transaction marked with propagation 'mandatory'
public void insertUser(String name) {
User user = new User();
user.setName(name);
userDao.insertUser(user);
stuService.insertStu(name);
throw new RuntimeException();
}
@Transactional(propagation = Propagation.MANDATORY)
public void insertStu(String name){
Stu stu = new Stu();
stu.setName(name);
stuDao.insertUser(stu);
}
6.NEVER
说明:不支持事务,如果当前存在事务,就抛出异常。
因为insertUser()配置了事务,所以在insertStu中会报错。
异常信息:Existing transaction found for transaction marked with propagation 'never'
@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
User user = new User();
user.setName(name);
userDao.insertUser(user);
stuService.insertStu(name);
//throw new RuntimeException();
}
@Transactional(propagation = Propagation.NEVER)
public void insertStu(String name){
Stu stu = new Stu();
stu.setName(name);
stuDao.insertUser(stu);
}
7.NESTED
说明:NESTED修饰的内部方法属于外部事务的子事务,外围主事务回滚,子事务一定回滚,而内部子事务可以单独回滚而不影响外围主事务和其他子事务
主要的场景可能是,下单的时候,送积分,如果下单失败,送积分也要回滚,但送积分失败不影响下单失败。这种场景可以使用这种传播性

浙公网安备 33010602011771号