色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

支付寶:多線程事務怎么回滾?

jf_ro2CN3Fa ? 來源:CSDN ? 2023-01-09 11:42 ? 次閱讀


背景介紹

1,最近有一個大數據量插入的操作入庫的業務場景,需要先做一些其他修改操作,然后在執行插入操作,由于插入數據可能會很多,用到多線程去拆分數據并行處理來提高響應時間,如果有一個線程執行失敗,則全部回滾。

2,在spring中可以使用@Transactional注解去控制事務,使出現異常時會進行回滾,在多線程中,這個注解則不會生效,如果主線程需要先執行一些修改數據庫的操作,當子線程在進行處理出現異常時,主線程修改的數據則不會回滾,導致數據錯誤。

3,下面用一個簡單示例演示多線程事務。

基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

  • 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 視頻教程:https://doc.iocoder.cn/video/

公用的類和方法

/**
*平均拆分list方法.
*@paramsource
*@paramn
*@param
*@return
*/
publicstaticList>averageAssign(Listsource,intn){
List>result=newArrayList>();
intremaider=source.size()%n;
intnumber=source.size()/n;
intoffset=0;//偏移量
for(inti=0;ivalue=null;
if(remaider>0){
value=source.subList(i*number+offset,(i+1)*number+offset+1);
remaider--;
offset++;
}else{
value=source.subList(i*number+offset,(i+1)*number+offset);
}
result.add(value);
}
returnresult;
}
/**線程池配置
*@versionV1.0
*/
publicclassExecutorConfig{
privatestaticintmaxPoolSize=Runtime.getRuntime().availableProcessors();
privatevolatilestaticExecutorServiceexecutorService;
publicstaticExecutorServicegetThreadPool(){
if(executorService==null){
synchronized(ExecutorConfig.class){
if(executorService==null){
executorService=newThreadPool();
}
}
}
returnexecutorService;
}

privatestaticExecutorServicenewThreadPool(){
intqueueSize=500;
intcorePool=Math.min(5,maxPoolSize);
returnnewThreadPoolExecutor(corePool,maxPoolSize,10000L,TimeUnit.MILLISECONDS,
newLinkedBlockingQueue<>(queueSize),newThreadPoolExecutor.AbortPolicy());
}
privateExecutorConfig(){}
}
/**獲取sqlSession
*@author86182
*@versionV1.0
*/
@Component
publicclassSqlContext{
@Resource
privateSqlSessionTemplatesqlSessionTemplate;

publicSqlSessiongetSqlSession(){
SqlSessionFactorysqlSessionFactory=sqlSessionTemplate.getSqlSessionFactory();
returnsqlSessionFactory.openSession();
}
}

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

  • 項目地址:https://github.com/YunaiV/yudao-cloud
  • 視頻教程:https://doc.iocoder.cn/video/

示例事務不成功操作

/**
*測試多線程事務.
*@paramemployeeDOList
*/
@Override
@Transactional
publicvoidsaveThread(ListemployeeDOList){
try{
//先做刪除操作,如果子線程出現異常,此操作不會回滾
this.getBaseMapper().delete(null);
//獲取線程池
ExecutorServiceservice=ExecutorConfig.getThreadPool();
//拆分數據,拆分5份
List>lists=averageAssign(employeeDOList,5);
//執行的線程
Thread[]threadArray=newThread[lists.size()];
//監控子線程執行完畢,再執行主線程,要不然會導致主線程關閉,子線程也會隨著關閉
CountDownLatchcountDownLatch=newCountDownLatch(lists.size());
AtomicBooleanatomicBoolean=newAtomicBoolean(true);
for(inti=0;iif(i==lists.size()-1){
atomicBoolean.set(false);
}
Listlist=lists.get(i);
threadArray[i]=newThread(()->{
try{
//最后一個線程拋出異常
if(!atomicBoolean.get()){
thrownewServiceException("001","出現異常");
}
//批量添加,mybatisPlus中自帶的batch方法
this.saveBatch(list);
}finally{
countDownLatch.countDown();
}

});
}
for(inti=0;i//當子線程執行完畢時,主線程再往下執行
countDownLatch.await();
System.out.println("添加完畢");
}catch(Exceptione){
log.info("error",e);
thrownewServiceException("002","出現異常");
}finally{
connection.close();
}
}

數據庫中存在一條數據:

07f6f516-8fc2-11ed-bfe3-dac502259ad0.png
//測試用例
@RunWith(SpringRunner.class)
@SpringBootTest(classes={ThreadTest01.class,MainApplication.class})
publicclassThreadTest01{

@Resource
privateEmployeeBOemployeeBO;

/**
*測試多線程事務.
*@throwsInterruptedException
*/
@Test
publicvoidMoreThreadTest2()throwsInterruptedException{
intsize=10;
ListemployeeDOList=newArrayList<>(size);
for(inti=0;inewEmployeeDO();
employeeDO.setEmployeeName("lol"+i);
employeeDO.setAge(18);
employeeDO.setGender(1);
employeeDO.setIdNumber(i+"XX");
employeeDO.setCreatTime(Calendar.getInstance().getTime());
employeeDOList.add(employeeDO);
}
try{
employeeBO.saveThread(employeeDOList);
System.out.println("添加成功");
}catch(Exceptione){
e.printStackTrace();
}
}
}

測試結果:

08028656-8fc2-11ed-bfe3-dac502259ad0.png08120248-8fc2-11ed-bfe3-dac502259ad0.png

可以發現子線程組執行時,有一個線程執行失敗,其他線程也會拋出異常,但是主線程中執行的刪除操作,沒有回滾,@Transactional注解沒有生效。

使用sqlSession控制手動提交事務

@Resource
SqlContextsqlContext;
/**
*測試多線程事務.
*@paramemployeeDOList
*/
@Override
publicvoidsaveThread(ListemployeeDOList)throwsSQLException{
//獲取數據庫連接,獲取會話(內部自有事務)
SqlSessionsqlSession=sqlContext.getSqlSession();
Connectionconnection=sqlSession.getConnection();
try{
//設置手動提交
connection.setAutoCommit(false);
//獲取mapper
EmployeeMapperemployeeMapper=sqlSession.getMapper(EmployeeMapper.class);
//先做刪除操作
employeeMapper.delete(null);
//獲取執行器
ExecutorServiceservice=ExecutorConfig.getThreadPool();
List>callableList=newArrayList<>();
//拆分list
List>lists=averageAssign(employeeDOList,5);
AtomicBooleanatomicBoolean=newAtomicBoolean(true);
for(inti=0;iif(i==lists.size()-1){
atomicBoolean.set(false);
}
Listlist=lists.get(i);
//使用返回結果的callable去執行,
Callablecallable=()->{
//讓最后一個線程拋出異常
if(!atomicBoolean.get()){
thrownewServiceException("001","出現異常");
}
returnemployeeMapper.saveBatch(list);
};
callableList.add(callable);
}
//執行子線程
List>futures=service.invokeAll(callableList);
for(Futurefuture:futures){
//如果有一個執行不成功,則全部回滾
if(future.get()<=0){
connection.rollback();
return;
}
}
connection.commit();
System.out.println("添加完畢");
}catch(Exceptione){
connection.rollback();
log.info("error",e);
thrownewServiceException("002","出現異常");
}finally{
connection.close();
}
}
//sql
"saveBatch"parameterType="List">
INSERTINTO
employee(employee_id,age,employee_name,birth_date,gender,id_number,creat_time,update_time,status)
values
="list"item="item"index="index"separator=",">
(
#{item.employeeId},
#{item.age},
#{item.employeeName},
#{item.birthDate},
#{item.gender},
#{item.idNumber},
#{item.creatTime},
#{item.updateTime},
#{item.status}
)


數據庫中一條數據:

081f036c-8fc2-11ed-bfe3-dac502259ad0.png

測試結果:拋出異常,

0836bc00-8fc2-11ed-bfe3-dac502259ad0.png

刪除操作的數據回滾了,數據庫中的數據依舊存在,說明事務成功了。

0847e7d2-8fc2-11ed-bfe3-dac502259ad0.png

成功操作示例:

@Resource
SqlContextsqlContext;
/**
*測試多線程事務.
*@paramemployeeDOList
*/
@Override
publicvoidsaveThread(ListemployeeDOList)throwsSQLException{
//獲取數據庫連接,獲取會話(內部自有事務)
SqlSessionsqlSession=sqlContext.getSqlSession();
Connectionconnection=sqlSession.getConnection();
try{
//設置手動提交
connection.setAutoCommit(false);
EmployeeMapperemployeeMapper=sqlSession.getMapper(EmployeeMapper.class);
//先做刪除操作
employeeMapper.delete(null);
ExecutorServiceservice=ExecutorConfig.getThreadPool();
List>callableList=newArrayList<>();
List>lists=averageAssign(employeeDOList,5);
for(inti=0;ilist=lists.get(i);
Callablecallable=()->employeeMapper.saveBatch(list);
callableList.add(callable);
}
//執行子線程
List>futures=service.invokeAll(callableList);
for(Futurefuture:futures){
if(future.get()<=0){
connection.rollback();
return;
}
}
connection.commit();
System.out.println("添加完畢");
}catch(Exceptione){
connection.rollback();
log.info("error",e);
thrownewServiceException("002","出現異常");
//thrownewServiceException(ExceptionCodeEnum.EMPLOYEE_SAVE_OR_UPDATE_ERROR);
}
}

測試結果:

08585db0-8fc2-11ed-bfe3-dac502259ad0.png

數據庫中數據:

刪除的刪除了,添加的添加成功了,測試成功。

0869dc84-8fc2-11ed-bfe3-dac502259ad0.png

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 多線程
    +關注

    關注

    0

    文章

    278

    瀏覽量

    20022
  • spring
    +關注

    關注

    0

    文章

    340

    瀏覽量

    14358

原文標題:支付寶:多線程事務怎么回滾?說用 @Transactional 可以回去等通知了!

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    支付寶發布新一代AI視覺搜索“探一下”

    支付寶近日正式推出了基于自研多模態大模型技術的新一代AI視覺搜索產品——“探一下”。這一創新產品的問世,標志著支付寶在AI技術應用領域邁出了重要一步。 “探一下”通過集成先進的AI技術,使用戶能夠
    的頭像 發表于 12-31 10:49 ?145次閱讀

    socket 多線程編程實現方法

    在現代網絡編程中,多線程技術被廣泛應用于提高服務器的并發處理能力。Socket編程是網絡通信的基礎,而將多線程技術應用于Socket編程,可以顯著提升服務器的性能。 多線程編程的基本概念 多線
    的頭像 發表于 11-12 14:16 ?403次閱讀

    支付寶與華為終端達成戰略合作

    近日,支付寶與華為終端正式宣布達成戰略合作,共同致力于鴻蒙生態與碰一下生態的深度融合與發展。
    的頭像 發表于 11-11 14:46 ?354次閱讀

    eBay攜手螞蟻國際旗下Antom,支付寶成eBay新支付選項

    近日,eBay宣布與螞蟻國際旗下的Antom達成合作,正式將支付寶納入其支付選項,為中國內地買家提供更加便捷、安全的支付體驗。 此次合作意味著,中國內地消費者在eBay平臺上購物時,可直接使用
    的頭像 發表于 11-11 13:56 ?467次閱讀

    支付寶與華為終端達成戰略合作,共同推動移動支付進入“碰時代”

    近日,支付寶與華為終端宣布了一項重要的戰略合作。此次合作將圍繞鴻蒙生態與支付寶的“碰一下”生態展開,旨在為用戶提供更加便捷、高效的移動支付體驗。 根據雙方簽署的戰略合作協議,華為將通過軟硬件的全面
    的頭像 發表于 11-10 11:16 ?690次閱讀

    Spring事務實現原理

    作者:京東零售 范錫軍 1、引言 spring的spring-tx模塊提供了對事務管理支持,使用spring事務可以讓我們從復雜的事務處理中得到解脫,無需要去處理獲得連接、關閉連接、事務
    的頭像 發表于 11-08 10:10 ?847次閱讀
    Spring<b class='flag-5'>事務</b>實現原理

    Python中多線程和多進程的區別

    Python作為一種高級編程語言,提供了多種并發編程的方式,其中多線程與多進程是最常見的兩種方式之一。在本文中,我們將探討Python中多線程與多進程的概念、區別以及如何使用線程池與進程池來提高并發執行效率。
    的頭像 發表于 10-23 11:48 ?426次閱讀
    Python中<b class='flag-5'>多線程</b>和多進程的區別

    ESP32會不會有多線程問題,需要加鎖嗎?

    ESP32會不會有多線程問題,需要加鎖嗎
    發表于 07-19 08:05

    復旦微電 Boost Tag 芯片助力支付寶NFC支付

    隨著技術的進步,移動支付技術正快速更新迭代。近日,支付寶正式推出NFC支付功能,用戶只需將手機“碰一碰”收銀臺NFC支付設備,即可輕松完成支付
    的頭像 發表于 07-12 18:02 ?2217次閱讀

    歡創播報 支付寶“碰一下”正式發布

    1 支付寶“碰一下”正式發布 近日,在支付寶開放日上,支付寶宣布升級條碼支付體驗,推出“支付寶碰一下”,用戶無需展示付款碼,解鎖手機碰一下商
    的頭像 發表于 07-11 11:32 ?915次閱讀
    歡創播報  <b class='flag-5'>支付寶</b>“碰一下”正式發布

    多線程設計模式到對 CompletableFuture 的應用

    最近在開發 延保服務 頻道頁時,為了提高查詢效率,使用到了多線程技術。為了對多線程方案設計有更加充分的了解,在業余時間讀完了《圖解 Java 多線程設計模式》這本書,覺得收獲良多。本篇文章將介紹其中
    的頭像 發表于 06-26 14:18 ?374次閱讀
    從<b class='flag-5'>多線程</b>設計模式到對 CompletableFuture 的應用

    利用Swap模式實現代碼操作

    前面介紹了MCUboot的基礎知識,您可通過上方鏈接回顧歷史文章,上次介紹了Swap模式,本次著重介紹利用Swap模式實現代碼操作。在某些應用場景中,可能新版本的Firmware存在bug而需要返回至上一次的固件。
    的頭像 發表于 06-19 15:45 ?1325次閱讀
    利用Swap模式實現代碼<b class='flag-5'>回</b><b class='flag-5'>滾</b>操作

    bootloader開多線程做引導程序,跳app初始化后直接進hardfualt,為什么?

    如標題,想做一個遠程升級的項目,bootloader引導區域和app都是開多線程跑的,就是自己寫了個小的任務調度器,沒什么功能主要是想讓程序快速的響應,延時不會對其他程序造成堵塞,程序測試
    發表于 04-18 06:07

    java實現多線程的幾種方式

    Java實現多線程的幾種方式 多線程是指程序中包含了兩個或以上的線程,每個線程都可以并行執行不同的任務或操作。Java中的多線程可以提高程序
    的頭像 發表于 03-14 16:55 ?755次閱讀

    AT socket可以多線程調用嗎?

    請問AT socket 可以多線程調用嗎? 有互鎖機制嗎,還是要自己做互鎖。
    發表于 03-01 08:22
    主站蜘蛛池模板: 国产午夜婷婷精品无码A片| 亚洲免费片| 国产视频a在线观看v| 5g在线视讯年龄确认海外禁止进入| 玩弄朋友娇妻呻吟交换电影 | 成人a视频在线观看| 亚洲中文久久精品AV无码| 失禁h啪肉尿出来高h| 欧美丰满白嫩bbxx| 久久国产欧美| 国产在线观看99| 国产超碰AV人人做人人爽| 99久久全国免费久久爱| 亚洲呦女专区| 亚洲精品久久YY5099| 甜宠溺H宝贝嗯撞PLAY啊| 欧美在线视频一区| 免费看国产曰批40分钟| 久久久久久久久久综合情日本 | 色哦色哦哦色天天综合| 内射后入在线观看一区| 看电影就来5566先锋av| 精品久久久无码21P发布| 日本免费xxx| 麻豆E奶女教师国产精品| 狠狠色狠狠色综合日日2019| 国产精品免费大片| 东京热无码中文字幕av专区| qvod伦理片| CHESENGAY痞帅警察GV| 757一本到午夜宫| 13小箩利洗澡无码视频APP| 一级特黄aa大片欧美| 亚洲无遮挡无码A片在线| 亚洲精品乱码久久久久久v| 亚洲国产在线观看免费视频| 亚洲粉嫩美白在线| 亚洲国产精品免费线观看视频| 午夜特级毛片| 性xxx在线观看| 亚洲精品天堂在线|