spring事务传播的Propagation.REQUIRES_NEW以及NEVER MANDATORY验证,及其 ...

打印 上一主题 下一主题

主题 831|帖子 831|积分 2493

NEVER

不使用事务,如果当前事务存在,则抛出异常
验证:
  1. @Service
  2. public class PrService {
  3.     @Autowired
  4.     PrDao dao;   
  5.     @Transactional
  6.     public void savea() {
  7.         dao.a();//保存第一条数据
  8.         saveb();
  9.     }
  10.     @Transactional(propagation = Propagation.NEVER)
  11.     private void saveb() {
  12.         dao.b();//保存第二条数据
  13.         int i=1/0;
  14.     }
  15. }
复制代码
写一个controller调用这个savea方法,页面看到的是/ by zero,数据库中两条数据都没有插入进去,都回滚了。照说设置了Propagation.NEVER,应该saveb方法根本执行不了,报never的错。为什么执行了呢?
因为是直接调用的saveb(),不是从代理对象上调用的方法,改成这样:
  1. @Service
  2. public class PrService {
  3.     @Autowired
  4.     PrDao dao;
  5.    
  6.     @Autowired
  7.     PrService prService;
  8.    
  9.     @Transactional
  10.     public void savea() {
  11.         dao.a();//保存第一条数据
  12.         prService.saveb();
  13.     }
  14.     @Transactional(propagation = Propagation.NEVER)
  15.     private void saveb() {
  16.         dao.b();//保存第二条数据
  17.         int i=1/0;
  18.     }
  19. }
复制代码
注意这里是  prService.saveb()和前面不同,但是居然在  dao.b(); 这一行报了一个空指针的错误,这就诡异了,这个dao明明上a方法里面还有值的,你知道是为什么吗?
原来b方法的修饰符是private,导致代理对象无法继承这个方法。改成public
  1. public void saveb()
复制代码
再次测试,看到期待的报错了:
  1. Existing transaction found for transaction marked with propagation 'never'
复制代码
 
 
MANDATORY

当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常。
这里把MANDATORY放在b方法上,就要把a方法上的transactional注解去掉,才能看到报错。
  1. @Service
  2. public class PrService {
  3.     @Autowired
  4.     PrDao dao;
  5.    
  6.     @Autowired
  7.     PrService prService;
  8.     public void savea() {
  9.         dao.a();//保存第一条数据
  10.         prService.saveb();
  11.     }
  12.     @Transactional(propagation = Propagation.MANDATORY)
  13.     public void saveb() {
  14.         dao.b();//保存第二条数据
  15.     }
  16. }
复制代码
或者直接把MANDATORY放在a方法上也会报错:
  1. @Service
  2. public class PrService {
  3.     @Transactional(propagation = Propagation.MANDATORY)
  4.     public void savea() {
  5.     }
  6. }
复制代码
报错如下
  1. No existing transaction found for transaction marked with propagation 'mandatory'
复制代码
 
REQUIRES_NEW
创建一个新事务,如果存在当前事务,则挂起该事务。
可以理解为设置事务传播类型为REQUIRES_NEW的方法,在执行时,不论当前是否存在事务,总是会新建一个事务。
现在写一个demo验证,a方法调用b方法,希望b方法里面异常了且事务回滚,a方法里面不回滚
下面验证:
同样为了在避免事务失效,在代理对象上调用方法,将被调用的方法放到一个单独的类中:
  1. @Service
  2. public class PrService {
  3.     @Autowired
  4.     PrDao dao;
  5.     @Autowired
  6.     SaveBService saveBService;
  7.     @Transactional
  8.     public void savea() {
  9.         dao.a();//插入第一条数据
  10.         saveBService.saveb();
  11.     }
  12. }
复制代码
  1. @Service
  2. public class SaveBService {
  3.     @Autowired
  4.     PrDao dao;
  5.     @Transactional(propagation = Propagation.REQUIRES_NEW)
  6.     public void saveb() {
  7.         dao.b();//插入第二条数据
  8.         int i = 1/0;
  9.     }
  10. }
复制代码
这里PrService的savea方法调用SaveBService的saveb方法,写一个controller访问savea方法,页面看到一个异常 / by zero,再检查数据库,两条数据都有没有插入进去。这是为什么呢?看上去第二个方法已经写到独立的类中了。
原来是因为b方法抛出的异常a方法没有捕获,又抛出去了,当然要回滚了。写个try catch就行:
  1.     @Transactional
  2.     public void savea() {
  3.         dao.a();//插入第一条数据
  4.         try {
  5.             saveBService.saveb();
  6.         }catch (Exception e) {
  7.             System.out.println("some error");
  8.         }
  9.     }
复制代码
再次测试,第二条数据没有插入,第一条数据插入到数据库了,页面也看不到报错了。
  
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

徐锦洪

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表