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事务里面开启线程插入,报错了是否会回滚?的更多相关文章

  1. Spring事务管理只对出现运行期异常进行回滚

    原文:http://blog.csdn.net/abc19900828/article/details/39497631 使用spring难免要用到spring的事务管理,要用事务管理又会很自然的选择 ...

  2. spring事务的开启方式(编程式和声明式)

    1.编程式事务:编码方式实现事务管理(代码演示为JDBC事务管理) Spring实现编程式事务,依赖于2大类,分别是上篇文章提到的PlatformTransactionManager,与模版类Tran ...

  3. Spring事务明明开启了,为什么没起作用???

    一.事务的特性(ACID) 1.原子性(Atomicity):事务是一个原子操作,由一系列动作组成.事务的原子性确保动作要么全部完成,要么完全不起作用. 2.一致性(Consistency):执行事务 ...

  4. spring data jpa开启批量插入、批量更新

    spring data jpa开启批量插入.批量更新 原文链接:https://www.cnblogs.com/blog5277/p/10661096.html 原文作者:博客园--曲高终和寡 *** ...

  5. 关于Spring事务的原理,以及在事务内开启线程,连接池耗尽问题.

    主要以结果为导向解释Spring 事务原理,连接池的消耗,以及事务内开启事务线程要注意的问题. Spring 事务原理这里不多说,网上一搜一大堆,也就是基于AOP配合ThreadLocal实现. 这里 ...

  6. Spring的事务传播性与隔离级别以及实现事物回滚

    一.事务的四个特性(ACID) 原子性(Atomicity):一个事务中所有对数据库的操作是一个不可分割的操作序列,要么全做,要么全部做. 一致性(Consistency): 数据不会因为事务的执行而 ...

  7. tp5 回滚事务记录,其中一条语句报错,全部回滚

    #################################### 测试事务 // 启动事务 Db::startTrans(); try { //插入行为表 $data = [ 'userId' ...

  8. Spring事务的开启方式

    1.通过注解方式@Transactional @Transactional(rollbackForClassName = { "Exception", "RuntimeE ...

  9. 手写Spring事务框架

    Spring事务基于AOP环绕通知和异常通知 编程事务 声明事务 Spring事务底层使用编程事务+AOP进行包装的   = 声明事务 AOP应用场景:  事务 权限 参数验证 什么是AOP技术 AO ...

  10. java异常与spring事务关系的知识点查漏补缺

    一.基础概念 java的异常结构图 从图中可知 Throwable是所有异常的根,java.lang.Throwable Error是错误,java.lang.Error Exception是异常,j ...

随机推荐

  1. linux 修改password

    passwd 命令,手动修改: [root@localhost testuser]# passwd testuser Changing password for user testuser. New ...

  2. 6vue分支循环

    分支v-if <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  3. 【Unity】关于VS条件编译符号

    写在前面 起因:我在回顾LuaFramework_UGUI(作者Jarjin Lee)代码时,看到了C#代码中的条件编译符号,比如下图的ASYNC_MODE.虽然字面上知道是什么意思,但我对VS的条件 ...

  4. 狂神的学习笔记demo0607

    Ctrl+D 复制此行到下一行 sout   快捷打出System.out.println(); 修饰符 static 静态的 finalf 常量 变量的命名规范 见名知意 类成员变量:首字母小写和驼 ...

  5. nRF52832出现“APP_UART_COMMUNICATION_ERROR”的错误的问题

    在调试nRF52832的uart的过程中,发现调试信息会时不时打印"APP_UART_COMMUNICATION_ERROR"这个错误,看上去似乎毫无规律.查看SDK的相关说明,可 ...

  6. 【QT5】学习整理包含引用资料

    视频学习资料 [[6天学会QT] 视频教程及QT5.11.1安装包安装方法][含代码]](https://www.bilibili.com/video/BV1hg4y1B7Vu?from=search ...

  7. 腾讯云等Linux环境下Redis安装配置

    1.下载redis解压安装命令教程 https://www.cnblogs.com/hunanzp/p/12304622.html 2.配置远程连接 修改bind 127.0.0.0  为 bind ...

  8. python之pyqt5-第一个pyqt5程序-图像压缩工具(2.0版本)-小记

    (如想转载,请联系博主或贴上本博地址) 此篇为上一篇pyqt5图像压缩小工具改良版.因为比较简单,下面直接贴上代码. 效果图: # -*- coding: utf-8 -*- # Form imple ...

  9. Django视图中的请求与响应

    一 请求 一 限制http请求 视图中的request,实际上是django源码中的HTTPRequest的子类WSGIRequest类的实例对象,主要由django对客户端请求的http协议报文进行 ...

  10. rosetta Resfile语法和约束

    介绍 参考:https://www.rosettacommons.org/docs/latest/rosetta_basics/file_types/resfiles resfile包含输入到Pack ...