spring事务里面开启线程插入,报错了是否会回滚?
1.前言
一道非常有意思的面试题目。大概是这样子的,如果在一个事务中,开启线程进行插入更新等操作,如果报错了,事务是否会进行回滚
2.代码
示例1
@RequestMapping("/test/publish/submit")
public String testPublish1() {
log.info("start...");
transactionTemplate.execute(new TransactionCallback<String>() {
@Override
public 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 testPublish2() {
log.info("start...");
transactionTemplate.execute(new TransactionCallback<String>() {
@Override
public 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
@Nullable
public <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 -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Throwable ex) {
// Transactional code threw unexpected exception -> rollback
rollbackOnException(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
4.最后
这道面试题非常有意思,起初以为会回滚,没想到不会回滚。查看代码得知,原来是catch住的是主线程,并不是子线程。同样注解式事务类似。因此如果想要事务生效,尽量避免在事务中使用多线程来进行插入更新等操作
spring事务里面开启线程插入,报错了是否会回滚?的更多相关文章
- Spring事务管理只对出现运行期异常进行回滚
原文:http://blog.csdn.net/abc19900828/article/details/39497631 使用spring难免要用到spring的事务管理,要用事务管理又会很自然的选择 ...
- spring事务的开启方式(编程式和声明式)
1.编程式事务:编码方式实现事务管理(代码演示为JDBC事务管理) Spring实现编程式事务,依赖于2大类,分别是上篇文章提到的PlatformTransactionManager,与模版类Tran ...
- Spring事务明明开启了,为什么没起作用???
一.事务的特性(ACID) 1.原子性(Atomicity):事务是一个原子操作,由一系列动作组成.事务的原子性确保动作要么全部完成,要么完全不起作用. 2.一致性(Consistency):执行事务 ...
- spring data jpa开启批量插入、批量更新
spring data jpa开启批量插入.批量更新 原文链接:https://www.cnblogs.com/blog5277/p/10661096.html 原文作者:博客园--曲高终和寡 *** ...
- 关于Spring事务的原理,以及在事务内开启线程,连接池耗尽问题.
主要以结果为导向解释Spring 事务原理,连接池的消耗,以及事务内开启事务线程要注意的问题. Spring 事务原理这里不多说,网上一搜一大堆,也就是基于AOP配合ThreadLocal实现. 这里 ...
- Spring的事务传播性与隔离级别以及实现事物回滚
一.事务的四个特性(ACID) 原子性(Atomicity):一个事务中所有对数据库的操作是一个不可分割的操作序列,要么全做,要么全部做. 一致性(Consistency): 数据不会因为事务的执行而 ...
- tp5 回滚事务记录,其中一条语句报错,全部回滚
#################################### 测试事务 // 启动事务 Db::startTrans(); try { //插入行为表 $data = [ 'userId' ...
- Spring事务的开启方式
1.通过注解方式@Transactional @Transactional(rollbackForClassName = { "Exception", "RuntimeE ...
- 手写Spring事务框架
Spring事务基于AOP环绕通知和异常通知 编程事务 声明事务 Spring事务底层使用编程事务+AOP进行包装的 = 声明事务 AOP应用场景: 事务 权限 参数验证 什么是AOP技术 AO ...
- java异常与spring事务关系的知识点查漏补缺
一.基础概念 java的异常结构图 从图中可知 Throwable是所有异常的根,java.lang.Throwable Error是错误,java.lang.Error Exception是异常,j ...
随机推荐
- pytorch卷积模块
nn.Conv2d() 常用的参数有in_channels,out_channels,kernel_size,stride,padding; 除此之外还有参数dilation,groups,bias ...
- NOIP2010普及组
T2]接水问题 有一些小细节,比如如果最小值存在多个,比如最后还需要一个完全结束的最大值 #include<iostream> #include<cstring> #inclu ...
- samba缓存问题
samba 在第一次登录时,会在windows上缓存着登录密码,当你重新修改samba服务端的密码, 再次登录时,windows会自动用缓存的旧密码登录,导致的登录失败.
- The difference of src and href
href是Hypertext Reference的缩写,表示超文本引用.用来建立当前元素和文档之间的链接.常用的有:link.a.例如: <link href="reset.css&q ...
- JSON反序列化接口的问题
今天在使用JSON序列化类时出现问题,原来类中有一个接口,在反序列化时不知道接口的实体是什么 public class Device : IComparer { private str ...
- selenium---xpath定位方法详解
Xpath定位 验证xpath写的是否正确: 1.打开浏览器检查页面,Ctrl+F,把路径输入进去,如果可以定位到的位置只有一个,说明是对的 2.在需要定位的页面,按F12后,切换至console ...
- HTML-CSS常用代码
注释标签:对代码进行说明<!-- 单行注释,也可以对多行文字进行注释 -->常用格式标签<b>加粗</b> <i>斜体</i> <u& ...
- Spring-设计模式
1.1开闭原则 开闭原则(open-closed principle,OCP)是指一个软件实体(如类,模块和函数)应该对扩展开放,对修改关闭.所谓的开闭,也正是对扩展和修改两个行为的一个原则. 强调用 ...
- Android studio手机界面的显示
终于显示出来啦! 前几天因为SDK的地址错误一直不显示,现在终于显示出来啦! 关于报错原因的话,我也不太清楚是咋解决的,就改了改Android studio软件里面下载SDK的地址,就出来啦!(只要报 ...
- Python学习笔记--函数来啦!
函数 函数,就是组织好的,可重复使用的,用来实现特定功能的代码块 实际的小案例:不使用内置函数len,利用函数知识计算出字符串的长度 实现: 函数的基础定义语法 案例:自动查核酸 实现: 函数的传入参 ...