Springboot?手動分頁查詢分批批量插入數(shù)據(jù)的實現(xiàn)流程
前言
業(yè)務(wù)場景是什么?
就是數(shù)據(jù)庫的一批數(shù)據(jù),量不少,需要執(zhí)行同步插入到別的地方。
簡單點肯定是一次性查出來,然后循環(huán)一個個插入,完事。
考慮點:
① 數(shù)據(jù)量大,一次性查出來操作,很爆炸。
② 循環(huán)里面一次一次地去插入,如果非業(yè)務(wù)場景必要,基本是不會在循環(huán)里面使用sql操作的。
所以該篇作為拋磚引玉(還有很多需要考慮的點),給出一種解決上面場景的代碼編寫方案, 手動分頁,查詢后批量插入。
正文
實現(xiàn)的流程簡圖:
看看最終實現(xiàn)的效果,通過代碼日志記錄了這個實現(xiàn)后的效果 :
開始實戰(zhàn):
代碼大體就這樣:
代碼:
//獲取數(shù)據(jù)總計數(shù) UserQueryCondition userQueryCondition=new UserQueryCondition(); Integer totalCount = userService.getAllUserCount(userQueryCondition); //每批同步的數(shù)據(jù)條數(shù) Integer batchSizeLimit = 500; //分批切割處理 List<PageLimitDTO> pageLimitGroupList = getPageLimitGroupList(totalCount, batchSizeLimit); int count=1; //物理批次查詢 for (PageLimitDTO pageBatchLimit:pageLimitGroupList){ List<User> pageBatchList = userService.getPageList( userQueryCondition, pageBatchLimit.getCurrIndex(), pageBatchLimit.getPageSize() ); if (!CollectionUtils.isEmpty(pageBatchList)){ //批量插入 Boolean syncAddResult = userSyncService.batchSyncAdd(pageBatchList); //做其余業(yè)務(wù) if (syncAddResult){ log.info("第{}次,user數(shù)據(jù)批量插入成功",count); } } log.info("第{}批次,user數(shù)據(jù)同步批量插入業(yè)務(wù)結(jié)束執(zhí)行",count); count=count+1; }
切割函數(shù)getPageLimitGroupList:
public List<PageLimitDTO> getPageLimitGroupList(Integer totalCount, Integer batchSizeLimit ) { log.info("這一次處理的總數(shù)據(jù)條數(shù)為 ={} 條, 每一批次處理條數(shù)為 ={} 條,現(xiàn)在開始做分批切割處理。",totalCount,batchSizeLimit); int pageNum = totalCount / batchSizeLimit; int surplus = totalCount % batchSizeLimit; if (surplus > 0) { pageNum = pageNum + 1; } List<PageLimitDTO> pageLimitGroupList =new LinkedList<>(); for(int i = 0; i < pageNum; i++){ Integer currIndex = i * batchSizeLimit; PageLimitDTO pageLimitDTO=new PageLimitDTO(); pageLimitDTO.setPageSize(batchSizeLimit); pageLimitDTO.setCurrIndex(currIndex); pageLimitDTO.setDealDataCount(currIndex+batchSizeLimit); pageLimitGroupList.add(pageLimitDTO); log.info("分批切割,第={}次,每次={}條,最終會處理到={}條。",pageLimitGroupList.size(),batchSizeLimit,currIndex+batchSizeLimit); } log.info("這一次處理的總數(shù)據(jù)條數(shù)為 ={} 條, 每一批次處理條數(shù)為 ={} 條,總共切割分成了 ={} 次,一切準(zhǔn)備就緒,可以開始批量插入。",totalCount,batchSizeLimit,pageLimitGroupList.size()); return pageLimitGroupList; }
物理分頁查詢的mybatis sql寫法示例(核心手動切割分頁查詢紅色部分):
代碼:
<select id="getPageList" resultMap="BaseResultMap"> SELECT * FROM user <where> <if test="merchantId != null and merchantId != 0"> and MERCHANT_ID = #{merchantId} </if> <if test="nameList != null and !nameList.isEmpty()"> and NAME in <foreach collection="nameList" separator="," open="(" close=")" item="name"> #{name} </foreach> </if> </where> LIMIT #{currIndex} , #{pageSize} </select>
批量插入示例:
<!--批量插入信息--> <insert id="batchSyncAdd" parameterType="java.util.List"> insert into user( id, name, age ) values <foreach collection="list" item="item" index="index" separator=","> ( #{item.id,jdbcType=BIGINT}, #{item.name,jdbcType=VARCHAR}, #{item.age,jdbcType=INTEGER} ) </foreach> </insert>
然后就是我們美如畫的,手動批次切割查詢插入:
當(dāng)前方案作為拋磚引玉,還有比較多可優(yōu)化的點,但是我不做擴展了,簡單列舉一下:
1. 每次切割分頁查詢,其實可以優(yōu)化。 例如取上一次的id作為下一次的起始條件。
2. 同步異步的封裝,可以更動態(tài)化。
3. 是否完全需要分批? 動態(tài)設(shè)置數(shù)據(jù)超過多少才開始分批切割,不超過,不需要走切割這些流程代碼。
到此這篇關(guān)于Springboot 手動分頁查詢,分批批量插入數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Springboot 分頁查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
OpenFeign在傳遞參數(shù)為對象類型是為空的問題
這篇文章主要介紹了OpenFeign在傳遞參數(shù)為對象類型是為空的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03java中優(yōu)化大量if...else...方法總結(jié)
在我們平時的開發(fā)過程中,經(jīng)常可能會出現(xiàn)大量If else的場景,代碼顯的很臃腫,非常不優(yōu)雅,下面這篇文章主要給大家介紹了關(guān)于java中優(yōu)化大量if...else...方法的相關(guān)資料,需要的朋友可以參考下2023-03-03Java中為什么重寫equals()也需要重寫hashCode方法
這篇文章主要介紹了Java中為什么重寫equals()也需要重寫hashCode(),本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04