spring事务传播有如下7种:
[1] 死活不要事务的
Propagation.NEVER:没有就非事务执行,有就抛出异常
Propagation.NOT_SUPPORTED:没有就非事务执行,有就直接挂起当前事务,然后非事务执行
[2] 可有可无的
Propagation.SUPPORTS:有就用,没有就算了
[3] 必须有事务的
Propagation.REQUIRES_NEW:有没有都新建事务,如果原来有事务,将原来的挂起
Propagation.NESTED:如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务
Propagation.REQUIRED:如果没有,就新建一个事务;如果有,就加入当前事务
Propagation.MANDATORY:如果没有,就抛出异常;如果有,就加入当前事务
下面代码演示:
//通用方法
/**
* 查找name的账户
* @author lsw
* @date 2022/5/26 11:16
*/
public Account getByName(String name){
Wrapper<Account> wrapper = new EntityWrapper<>();
wrapper.eq("name", name);
return this.accountMapper.selectList(wrapper).get(0);
}
1.Propagation.NEVER
1)NEVER不支持事务的情况
//下面是AccountServiceImpl.java 转出与转入的方法
/**
* 转出,张三余额-100
* @author lsw
* @date 2022/5/26 11:12
*/
@Transactional
public void test_never1(){
Account account = this.getByName("张三");
account.setBalance(account.getBalance() - 100d);
this.accountMapper.updateById(account);
try{
//注意,这里要用accountService来调用test_never2,不然事务会失效。
//这和aop的原理有关系;如果直接this调用的话,就不是用代理对象调用的了,就不会有事务。
accountService.test_never2();
}catch(Exception e){
e.printStackTrace();
}
int x = 10;
if(x == 10){
throw new NullPointerException("出错啦");
}
}
/**
* 转入,李四余额+100
* @author lsw
* @date 2022/5/26 11:12
*/
@Transactional(propagation = Propagation.NEVER)
public void test_never2(){
Account account = this.getByName("李四");
account.setBalance(account.getBalance() + 100d);
this.accountMapper.updateById(account);
int x = 10;
if(x == 10){
throw new NullPointerException("出错啦");
}
}
//如果的情况,启动工程会直接报错,因为调用never的地方,不能有事务
2)NEVER事务回滚情况
将test_never1方法的事务注释掉,此时工程可以正常启动。test_never1和test_never2都
没有事务。
执行accountService.test_never1,两个方法都报错,因为没有事务,所以数据不会回滚
AccountServiceImpl.java
/**
* 转出,张三余额-100
* @author lsw
* @date 2022/5/26 11:12
*/
//@Transactional
public void test_never1(){
Account account = this.getByName("张三");
account.setBalance(account.getBalance() - 100d);
this.accountMapper.updateById(account);
try{
//注意,这里要用accountService来调用test_never2,不然事务会失效。
//这和aop的原理有关系;如果直接this调用的话,就不是用代理对象调用的了,就不会有事务。
accountService.test_never2();
}catch(Exception e){
e.printStackTrace();
}
int x = 10;
if(x == 10){
throw new NullPointerException("出错啦");
}
}
/**
* 转入,李四余额+100
* @author lsw
* @date 2022/5/26 11:12
*/
@Transactional(propagation = Propagation.NEVER)
public void test_never2(){
Account account = this.getByName("李四");
account.setBalance(account.getBalance() + 100d);
this.accountMapper.updateById(account);
int x = 10;
if(x == 10){
throw new NullPointerException("出错啦");
}
}
Test.java
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {
@Autowired
AccountServiceImpl accountService;
@org.junit.Test
public void test(){
accountService.test_never1();
}
}
在上面的执行结果可以看出,张三账户少了100,李四账户多了100,事务没有回滚
2.Propagation.NOT_SUPPORTED
将数据还原,如下:
1)not_supported调用方存在事务的情况
/**
* 转出,张三余额-100
* @author lsw
* @date 2022/5/26 11:12
*/
@Transactional
public void test_not_supported1(){
Account account = this.getByName("张三");
account.setBalance(account.getBalance() - 100d);
this.accountMapper.updateById(account);
//注意,这里要用accountService来调用当前service其他方法,不然事务会失效。
//这和aop的原理有关系;如果直接this调用的话,就不是用代理对象调用的了,就不会有事务。
accountService.test_not_supported2();
}
/**
* 转入,李四余额+100
* @author lsw
* @date 2022/5/26 11:12
*/
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void test_not_supported2(){
Account account = this.getByName("李四");
account.setBalance(account.getBalance() + 100d);
this.accountMapper.updateById(account);
int x = 10;
if(x == 10){
throw new RuntimeException("出错啦");
}
}
@org.junit.Test
public void test_not_supported(){
accountService.test_not_supported1();
}
执行完test_not_supported之后,test_not_supported1中由于异常传递报错 事务回滚,test_not_supported2中因为没有事务,就算报错,事务也不会回滚。
2)not_supported调用方不存在事务的情况
数据还原
代码就不在这里贴了,相比1)中,就是把 test_not_supported1的Transational注释掉
由此看出,如果调用方不存在事务,test_not_supported1和test_not_supported2都
不会回滚。参考not_supported的传播特性。