欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

spring事務(wù)里面開啟線程插入報錯了是否會回滾

 更新時間:2023年04月13日 09:02:44   投稿:mrr  
這篇文章主要介紹了spring事務(wù)里面開啟線程插入,報錯了是否會回滾?這是小編遇到一道面試題,題目大概是這個樣子,今天抽空通過示例代碼給大家分析下,需要的朋友可以參考下

1.前言

一道非常有意思的面試題目。大概是這樣子的,如果在一個事務(wù)中,開啟線程進(jìn)行插入更新等操作,如果報錯了,事務(wù)是否會進(jìn)行回滾。

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.結(jié)論

示例1

element.setfElementId(10L); 為主鍵。SQL在第一次插入id=10的時候是沒有問題的,在第二次插入id=10的時候,由于主鍵沖突了,導(dǎo)致報錯,然后整個事務(wù)都會進(jìn)行回滾,這是沒有問題的。是spring的事務(wù)幫助我們來進(jìn)行回滾等操作的。我們可以看到如下代碼,他是對整個result = action.doInTransaction(status);進(jìn)行了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線程。然后在第一個子線程插入了一個數(shù)據(jù),第二個子線程也插入了一個數(shù)據(jù)。那么現(xiàn)在就是有三個線程,一個是main線程,一個是A線程,一個是B線程。
main線程正常執(zhí)行不報錯,A線程正常插入不報錯,B線程由于主鍵沖突報錯。
我們可以通過上面action.doInTransaction(status);看出來,他對這塊代碼進(jìn)行了try catch。也就是主線程進(jìn)行了try catch。那么也就是只要主線程沒有報錯,這個事務(wù)就不會被捕獲,也就不會回滾了。無論你A,B還是CDEFG子線程出問題了,只要不影響main線程,那事務(wù)就不會回滾呢?
因此我們可以得出一個結(jié)論,在示例2中,A線程會插入成功,B線程插入失敗,事務(wù)不會回滾,最終插入成功。這個其實與我們平常的想法所違背了。
因此如果想要主線程拋出異常,得讓主線程感知到子線程異常了,主動地去throw異常。比如我們可以設(shè)置一個flag,子線程報錯了 flag=true。主線程檢測到flag為true,就主動拋出一個exception

4.最后

這道面試題非常有意思,起初以為會回滾,沒想到不會回滾。查看代碼得知,原來是catch住的是主線程,并不是子線程。同樣注解式事務(wù)類似。因此如果想要事務(wù)生效,盡量避免在事務(wù)中使用多線程來進(jìn)行插入更新等操作

到此這篇關(guān)于spring事務(wù)里面開啟線程插入,報錯了是否會回滾?的文章就介紹到這了,更多相關(guān)spring事務(wù)開啟線程插入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論