返回顶部
首页 > 资讯 > 精选 >spring事务里面开启线程插入报错了会回滚吗
  • 600
分享到

spring事务里面开启线程插入报错了会回滚吗

2023-07-06 02:07:56 600人浏览 薄情痞子
摘要

这篇文章主要讲解了“spring事务里面开启线程插入报错了会回滚吗”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“spring事务里面开启线程插入报错了会回滚吗”吧!1.前言一道非常有意思的面

这篇文章主要讲解了“spring事务里面开启线程插入报错了会回滚吗”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“spring事务里面开启线程插入报错了会回滚吗”吧!

1.前言

一道非常有意思的面试题目。大概是这样子的,如果在一个事务中,开启线程进行插入更新等操作,如果报错了,事务是否会进行回滚。

2.代码

示例1

@RequestMapping("/test/publish/submit")public String testPublish2() {log.info("start...");transactionTemplate.execute(new TransactionCallback<String>() {@Overridepublic String doInTransaction(TransactionStatus status)  {TElement element = new TElement();element.setfElementId(10L);element.setfElementName("111");mapper.insertSelective(element);element = new TElement();element.setfElementId(10L);element.setfElementName("222");mapper.insertSelective(element);return "OK";}});log.info("end...");return "ok";}

示例2

@RequestMapping("/test/publish/submit2")public String testPublish3() {log.info("start...");transactionTemplate.execute(new TransactionCallback<String>() {@Overridepublic String doInTransaction(TransactionStatus status)  {es.submit(() -> {TElement element = new TElement();element.setfElementId(10L);element.setfElementName("111");mapper.insertSelective(element);});es.submit(() -> {TElement element = new TElement();element.setfElementId(10L);element.setfElementName("222");mapper.insertSelective(element);});return "OK";}});log.info("end...");return "ok";}

3.结论

示例1

element.setfElementId(10L); 为主键。sql在第一次插入id=10的时候是没有问题的,在第二次插入id=10的时候,由于主键冲突了,导致报错,然后整个事务都会进行回滚,这是没有问题的。是spring的事务帮助我们来进行回滚等操作的。我们可以看到如下代码,他是对整个result = action.doInTransaction(status);进行了try catch。如果抛异常,就会回滚

@Override@Nullablepublic <T> T execute(TransactionCallback<T> action) throws TransactionException {Assert.state(this.transactionManager != null, "No PlatfORMTransactionManager set");if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);}else {TransactionStatus status = this.transactionManager.getTransaction(this);T result;try {result = action.doInTransaction(status);}catch (RuntimeException | Error ex) {// Transactional code threw application exception -> rollbackrollbackOnException(status, ex);throw ex;}catch (Throwable ex) {// Transactional code threw unexpected exception -> rollbackrollbackOnException(status, ex);throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");}this.transactionManager.commit(status);return result;}}

示例2

示例2首先是transactionTemplate.execute是一个主main线程。然后在第一个子线程插入了一个数据,第二个子线程也插入了一个数据。那么现在就是有三个线程,一个是main线程,一个是A线程,一个是B线程。
main线程正常执行不报错,A线程正常插入不报错,B线程由于主键冲突报错。
我们可以通过上面action.doInTransaction(status);看出来,他对这块代码进行了try catch。也就是主线程进行了try catch。那么也就是只要主线程没有报错,这个事务就不会被捕获,也就不会回滚了。无论你A,B还是CDEFG子线程出问题了,只要不影响main线程,那事务就不会回滚呢?
因此我们可以得出一个结论,在示例2中,A线程会插入成功,B线程插入失败,事务不会回滚,最终插入成功。这个其实与我们平常的想法所违背了。
因此如果想要主线程抛出异常,得让主线程感知到子线程异常了,主动地去throw异常。比如我们可以设置一个flag,子线程报错了 flag=true。主线程检测到flag为true,就主动抛出一个exception

感谢各位的阅读,以上就是“spring事务里面开启线程插入报错了会回滚吗”的内容了,经过本文的学习后,相信大家对spring事务里面开启线程插入报错了会回滚吗这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: spring事务里面开启线程插入报错了会回滚吗

本文链接: https://lsjlt.com/news/357415.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作