spring事务里面开启线程插入,报错了是否会回滚?

这篇具有很好参考价值的文章主要介绍了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住的是主线程,并不是子线程。同样注解式事务类似。因此如果想要事务生效,尽量避免在事务中使用多线程来进行插入更新等操作文章来源地址https://www.toymoban.com/news/detail-411788.html

到了这里,关于spring事务里面开启线程插入,报错了是否会回滚?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 73.是否可以把我们所需的Bean都放入Spring­mvc子容器里面来管理(springmvc的spring-servlet.xml中配置全局扫描)?

    可以 , 因为父容器的体现无非是为了获取子容器不包含的bean, 如果全部包含在子容器完全用不到父容器了, 所以是可以全部放在springmvc子容器来管理的。 虽然可以这么做不过一般应该是不推荐这么去做的,一般人也不会这么干的。如果你的项目里有用到事物、或者aop记得也

    2024年02月21日
    浏览(47)
  • Spring中事务失效的8中场景 对于一个事务开子线程

    1. 数据库引擎不支持事务 这里以 MySQL为例,MyISAM引擎是不支持事务操作的,一般要支持事务都会使用InnoDB引擎,根据MySQL 的官方文档说明,从MySQL 5.5.5 开始的默认存储引擎是 InnoDB,之前默认的都是 MyISAM,所以这一点要值得注意,如果底层引擎不支持事务,那么再怎么设置也

    2024年02月16日
    浏览(39)
  • Spring boot 事务无效,报错:Transaction not enabled

    使用spring boot + mybatis plus时添加的事务不生效,并且有些方法操作会出现如下异常: 追踪SqlHelper类,找到报错的位置,如下: 可以看到只有批量插入才会报错,单条插入不报错。报错是因为得不到事务标识,猜测可能是事务注解没生效。 查找spring boot的事务使用方式,大多数

    2024年02月11日
    浏览(43)
  • Spring Boot Elasticsearch7.6.2实现创建索引、删除索引、判断索引是否存在、获取/添加/删除/更新索引别名、单条/批量插入、单条/批量更新、删除数据、递归统计ES聚合的数据

    注意:我的版本是elasticsearch7.6.2、spring-boot-starter-data-elasticsearch-2.5.6 引入依赖 有时候你可能需要查询大批量的数据,建议加上下面配置文件

    2024年02月13日
    浏览(74)
  • 如何确定22端口是否开启(确定ssh服务是否开启)

    远程连接必要的信息:     1. IP地址 网络上唯一的 类似家庭住址        10.0.0.200     2. 端口默认的22        端口对应着不同的服务 22--SSH服务(可以让用户通过远程工具连接我 类似于向日葵 类似QQ远程连接)            端口号类似于去公园  1--售票 2--退票 3---军人老人优

    2023年04月08日
    浏览(39)
  • mysql不同隔离级别事务插入数据

    面试中问到了相关问题,做下问题记录 问题是这样的,数据库默认隔离级别下,事务A插入一条数据,没有提交,事务B插入一条数据,提交,表id为自增,如果表是空表,事务A和事务B的id分别是多少。 2.1.1 打开一个mysql窗口,事务A 执行代码块 2.1.2 打开另一个窗口,事务B 执

    2024年02月11日
    浏览(53)
  • 如何开启SpringBoot的事务

    通过在方法或类上添加@Transactional注解,SpringBoot会自动为这些方法开启事务。如果方法调用期间发生异常,事务将回滚;如果方法成功执行,事务将提交。 代码演示 在上述例子中,我们在GradeService类的enterGrades方法上添加了@Transactional注解,这样Spring Boot会为该方法开启事务

    2024年02月09日
    浏览(68)
  • SpringBoot 开启事务的常用方式

    前言,有时候统一异常处理不太好,因为范围太广了,很多没必要回滚的地方,因为抛了个异常都没办法继续执行别的代码,所以,可以在需要开事务的地方添加 @Transation 注解开启事务就行了。 springboot 项目中,一般两种方式可以开启事务: 1. 只需要在类或者方法上添加注

    2024年02月16日
    浏览(54)
  • python 相关框架事务开启方式

    对于框架而言,各式API接口少不了伴随着事务的场景,下面就列举常用框架的事务开启方法 注:利用begin_nested方法,会开启一个子事务!实现数据库变更需将子事务提交再将主事务提交才行 2.1、样例模板 2.2、进化版

    2024年02月13日
    浏览(70)
  • 【vue】vue 里面使用 v-html 插入的文本带有换行符‘\n‘不换行

    最近开发vue2 项目 ,接口返回的是类似于这样的数据: 我是第一行的哦n我是第二行的哦 我是直接这样渲染的, 但结果却是不如意,变成了下面这样 1.在使用 v-html 时添加样式,white-space:pre-wrap ,让浏览器保留空白和换行符。 2、用 pre 标签包裹 被包围在 pre 标签中的文本通常

    2024年02月14日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包