首頁 > 軟體

Springboot 手動分頁查詢分批批次插入資料的實現流程

2022-07-05 22:01:45

前言

業務場景是什麼? 

就是資料庫的一批資料,量不少,需要執行同步插入到別的地方。

簡單點肯定是一次性查出來,然後迴圈一個個插入,完事。

考慮點:

① 資料量大,一次性查出來操作,很爆炸。

② 迴圈裡面一次一次地去插入,如果非業務場景必要,基本是不會在迴圈裡面使用sql操作的。

所以該篇作為拋磚引玉(還有很多需要考慮的點),給出一種解決上面場景的程式碼編寫方案, 手動分頁,查詢後批次插入。

正文

實現的流程簡圖:

看看最終實現的效果,通過程式碼紀錄檔記錄了這個實現後的效果 :

開始實戰:

程式碼大體就這樣:

 程式碼:

        //獲取資料總計數
        UserQueryCondition userQueryCondition=new UserQueryCondition();
        Integer totalCount = userService.getAllUserCount(userQueryCondition);
        //每批同步的資料條數
        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);
                //做其餘業務
                if (syncAddResult){
                    log.info("第{}次,user資料批次插入成功",count);
                }
            }
            log.info("第{}批次,user資料同步批次插入業務結束執行",count);
            count=count+1;
        }

切割函數getPageLimitGroupList:

    public List<PageLimitDTO> getPageLimitGroupList(Integer totalCount, Integer batchSizeLimit ) {
        log.info("這一次處理的總資料條數為 ={} 條, 每一批次處理條數為 ={} 條,現在開始做分批切割處理。",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("這一次處理的總資料條數為 ={} 條, 每一批次處理條數為 ={} 條,總共切割分成了 ={} 次,一切準備就緒,可以開始批次插入。",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>

然後就是我們美如畫的,手動批次切割查詢插入:

當前方案作為拋磚引玉,還有比較多可優化的點,但是我不做擴充套件了,簡單列舉一下:

1. 每次切割分頁查詢,其實可以優化。 例如取上一次的id作為下一次的起始條件。
2. 同步非同步的封裝,可以更動態化。
3. 是否完全需要分批? 動態設定資料超過多少才開始分批切割,不超過,不需要走切割這些流程程式碼。

到此這篇關於Springboot 手動分頁查詢,分批批次插入資料的文章就介紹到這了,更多相關Springboot 分頁查詢內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com