sp:Propagation.REQUIRED vs Propagation.REQUIRES_NEW
2016-05-04 17:16
471 查看
Introduction
spring事务propagation(事务传播特性)配置,常用的配置项为Propagation.REQUIRED或者Propagation.REQUIRES_NEW。Propagation.REQUIRED:如果当前有事务,则在当前事务中执行,如果没有事务,则创建一个事务执行。
Propagation.REQUIRES_NEW:无论如何创建一个新的事务执行。
这里的事务指的是数据库层面的事务(physical transaction)
如果在当前事务中,调用有@Transactional(Propagation.REQUIRED/REQUIRES_NEW)配置的方法,在该方法中触发了事务回滚条件,由于REQUIRED在当前事务中执行,所以当前事务会回滚,而REQUIRES_NEW新建一个事务,所以新建的事务会回滚,而当前事务是否回滚与此无关。
REQUIRED
@Service public class TestServiceImpl02 implements TestService { @Autowired private SmsUserMapper smsUserMapper; @Autowired private TestService testServiceImpl01; @Override @Transactional(propagation=Propagation.REQUIRED) public void test() { SmsUser user = new SmsUser(); user.setUserAccount("baizq000"); user.setUserPwd("000000"); user.setUserStatus(0); user.setPlatformName("xxx"); smsUserMapper.insert(user); testServiceImpl01.test();//在当前事务中调用下面的Propagation.REQUIRED方法 } }
@Service public class TestServiceImpl01 implements TestService { @Override @Transactional(propagation=Propagation.REQUIRED) public void test(){ throw new RuntimeException("xxx"); } }
调用TestServiceImpl02 .test()
结果:默认的rollbackFor RuntimeException导致testServiceImpl01.test()事务回滚,从而导致外部的事务(其实是同一个事务)也回滚,插入失败
打印的日志大概是这样:
Participating in existing transaction
Participating transaction failed - marking existing transaction as rollback-only
Initiating transaction rollback
Rolling back JDBC transaction on Connection[jdbc:mysql://…
Returning JDBC Connection to DataSource
REQUIRES_NEW
@Service public class TestServiceImpl02 implements TestService { @Autowired private SmsUserMapper smsUserMapper; @Autowired private TestService testServiceImpl01; @Override @Transactional(propagation=Propagation.REQUIRED) public void test() { SmsUser user = new SmsUser(); user.setUserAccount("baizq000"); user.setUserPwd("000000"); user.setUserStatus(0); user.setPlatformName("xxx"); smsUserMapper.insert(user); try{ testServiceImpl01.test();//在当前事务中调用下面的Propagation.REQUIRES_NEW方法 }catch(RuntimeException e){ e.printStackTrace(); } } }
@Service public class TestServiceImpl01 implements TestService { @Override @Transactional(propagation=Propagation.REQUIRES_NEW) public void test(){ throw new RuntimeException("xxx"); } }
调用TestServiceImpl02 .test()
结果,默认的rollbackFor RuntimeException导致testServiceImpl01.test()事务回滚,由于配置了REQUIRES_NEW,该事务为新的事务,与外部事务无关,观察外部事务,并不会触发回滚条件,所以外部事物可以成功执行,插入成功。
打印的日志大概是这样:
Suspending current transaction, creating new transaction with name [com.qyd.sms….
Resuming suspended transaction after completion of inner transaction
Initiating transaction commit
Committing JDBC transaction on Connection [jdbc:mysql://….
UnexpectedRollbackException
@Service public class TestServiceImpl02 implements TestService { @Autowired private SmsUserMapper smsUserMapper; @Autowired private TestService testServiceImpl01; @Override @Transactional(propagation=Propagation.REQUIRED) public void test() { SmsUser user = new SmsUser(); user.setUserAccount("baizq000"); user.setUserPwd("000000"); user.setUserStatus(0); user.setPlatformName("xxx"); smsUserMapper.insert(user); try{ testServiceImpl01.test(); //在当前事务中调用下面的Propagation.REQUIRED方法,与之前不同的是这里对异常做了处理。 }catch(RuntimeException e){ e.printStackTrace(); } } }
@Service public class TestServiceImpl01 implements TestService { @Override @Transactional(propagation= 4000 Propagation.REQUIRED) public void test(){ throw new RuntimeException("xxx"); } }
调用TestServiceImpl02 .test()
会有如下的异常输出:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
当调用testServiceImpl01.test();会导致当前事务被设置为rollback-only(从REQUIRED章节的日志–Participating transaction failed - marking existing transaction as rollback-only),
而外部事务对异常的处理,导致外部事务看不到异常,所以外部事务会认为当前事务是没有问题的,要执行提交操作,但是由于之前当前事务已经被设置为rollback-only,异常就是这样来的。
至于如何实现,暂时先不考虑了,借此聊以慰藉。
相关文章推荐
- Qt Gui使用(三)
- 个人能力怎么看?四个方面帮你量化UE&UI的绩效标准
- Qt Gui使用(二)
- 纯代码实现自定义UITableView的cell
- 在android studio中添加.jar文件后,rebuild不报错,执行报错的解决
- Qt Gui使用(一)
- java基础学习总结——GUI编程(二)
- jJMeter UDP Request:不等待服务器响应
- java基础学习总结——GUI编程(一)
- 生成器模式 (Builder)
- STL学习笔记— —特殊容器queue
- Java队列Queue、双端队列Deque
- keras中models的Squential类的源码简介
- iOS--Quartz2D使用(自定义UIImageView控件、绘制基本图形)
- UiViewController 里frame和bounds取值有误
- UESTC 491 Tricks in Bits
- UESTC 491 Tricks in Bits
- UESTC 485 Game(康托,BFS)
- UESTC 485 Game(康托,BFS)
- Unreal Engine 4 —— 冷却UI的制作