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系统环境下部署jar程序实现后台运行1

    [ nohup java -jar xxx.jar --spring.profiles.active=prod > 日志文件名 2>&1 & ]

  2. git push错误failed to push some refs to的解决

    问题说明 当我们在github版本库中发现一个问题后,你在github上对它进行了在线的修改:或者你直接在github上的某个库中添加readme文件或者其他什么文件,但是没有对本地库进行同步.这个时 ...

  3. cv2安装

    pip install opencv-contrib-python

  4. python3.5升级到3.6

    第一步: sudo apt-get install software-properties-common sudo add-apt-repository ppa:jonathonf/python-3. ...

  5. 关于SSD硬盘

    2月份,看到Netac的SSD硬盘便宜,入手一个720G的,把原来的三星250G换掉,有时感觉机器会卡,一直没注意,最近更新一个英睿达的MX系列500G放电脑里用,毕竟杂牌做主硬盘不放心.就把Neta ...

  6. PHP程序的“Missing argument 3”的错误提示解决方法

    是在定义函数时为三个参数,但实际调用时只调了两个参数   解决办法: 一种:在调用函数地方补全调用的参数 二种:修改函数传入参数值,设置带有默认值,     Missing argument 3 fo ...

  7. Mac下python2升级3

    1.下载python最新版本 链接:https://www.python.org/downloads/mac-osx/ 安装默认位置为: /Library/Frameworks/Python.fram ...

  8. Python项目案例开发从入门到实战-1.4Python图形界面设计

    Python提供了多个图形开发界面的库,常用的Python GUI库如下. -Tkinter:Python内置模块 -wxPython -Jython 1.4.1创建Windows窗口 import ...

  9. Switch问题

    package com.company;public class Main { public static void main(String[] args) { Income[] incomes = ...

  10. sql union 和 union all

    UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 但是需要注意: 1.union内部的select语句必须拥有相同数量的列. 2.列必须拥有相似的数据类型. 3.每条select语句 ...