您好,登錄后才能下訂單哦!
這篇文章主要講解了“spring事務(wù)里面開啟線程插入報(bào)錯(cuò)了會(huì)回滾嗎”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“spring事務(wù)里面開啟線程插入報(bào)錯(cuò)了會(huì)回滾嗎”吧!
一道非常有意思的面試題目。大概是這樣子的,如果在一個(gè)事務(wù)中,開啟線程進(jìn)行插入更新等操作,如果報(bào)錯(cuò)了,事務(wù)是否會(huì)進(jìn)行回滾。
示例1
@RequestMapping("/test/publish/submit") public String testPublish2() { 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 testPublish3() { 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"; }
示例1
element.setfElementId(10L); 為主鍵。SQL在第一次插入id=10的時(shí)候是沒有問題的,在第二次插入id=10的時(shí)候,由于主鍵沖突了,導(dǎo)致報(bào)錯(cuò),然后整個(gè)事務(wù)都會(huì)進(jìn)行回滾,這是沒有問題的。是spring的事務(wù)幫助我們來進(jìn)行回滾等操作的。我們可以看到如下代碼,他是對整個(gè)result = action.doInTransaction(status);進(jìn)行了try catch。如果拋異常,就會(huì)回滾
@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是一個(gè)主main線程。然后在第一個(gè)子線程插入了一個(gè)數(shù)據(jù),第二個(gè)子線程也插入了一個(gè)數(shù)據(jù)。那么現(xiàn)在就是有三個(gè)線程,一個(gè)是main線程,一個(gè)是A線程,一個(gè)是B線程。
main線程正常執(zhí)行不報(bào)錯(cuò),A線程正常插入不報(bào)錯(cuò),B線程由于主鍵沖突報(bào)錯(cuò)。
我們可以通過上面action.doInTransaction(status);看出來,他對這塊代碼進(jìn)行了try catch。也就是主線程進(jìn)行了try catch。那么也就是只要主線程沒有報(bào)錯(cuò),這個(gè)事務(wù)就不會(huì)被捕獲,也就不會(huì)回滾了。無論你A,B還是CDEFG子線程出問題了,只要不影響main線程,那事務(wù)就不會(huì)回滾呢?
因此我們可以得出一個(gè)結(jié)論,在示例2中,A線程會(huì)插入成功,B線程插入失敗,事務(wù)不會(huì)回滾,最終插入成功。這個(gè)其實(shí)與我們平常的想法所違背了。
因此如果想要主線程拋出異常,得讓主線程感知到子線程異常了,主動(dòng)地去throw異常。比如我們可以設(shè)置一個(gè)flag,子線程報(bào)錯(cuò)了 flag=true。主線程檢測到flag為true,就主動(dòng)拋出一個(gè)exception
感謝各位的閱讀,以上就是“spring事務(wù)里面開啟線程插入報(bào)錯(cuò)了會(huì)回滾嗎”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對spring事務(wù)里面開啟線程插入報(bào)錯(cuò)了會(huì)回滾嗎這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。