Mybatis-plus 大数据量数据流式查询通用接口
文章目錄
- 一、案例需求
- 二、使用案例:
- 2.1. 自定義查詢接口
- 2.2. 邏輯處理類
- 2.3. 調(diào)用案例
- 2.4. 具體邏輯處理案例
- 三、企業(yè)案例
- 3.1. key名稱獲取
- 3.2. 邏輯類測試
- 3.3.最后一個(gè)批次處理方案
- 四、 通用SQL預(yù)編譯處理
- 4.1. 業(yè)務(wù)場景
- 4.2. xml形式
- 4.3. 注解形式
- 五、企業(yè)案例
- 5.1. sql語句
- 5.2. 大數(shù)據(jù)流查詢接口
- 5.3. 大數(shù)據(jù)查詢結(jié)果集處理抽象類
- 5.4. 服務(wù)接口
- 5.5. 服務(wù)接口實(shí)現(xiàn)類
- 5.6. 前端控制器
聲明:
大數(shù)據(jù)流查詢解決查詢結(jié)果集過大的導(dǎo)致內(nèi)存溢出的問題。
針對(duì)查詢通用SQL與數(shù)據(jù)交互的次數(shù)加到數(shù)據(jù)庫壓力,要使用預(yù)編譯。
一、案例需求
查詢sys_user表中的所有數(shù)據(jù),數(shù)據(jù)庫中供3條數(shù)據(jù),在實(shí)際處理類中我設(shè)置了具體處理批次的數(shù)量為2條數(shù)據(jù)為一個(gè)批次,那么一個(gè)批次就只處理2條數(shù)據(jù),處理完成后,繼續(xù)處理下一個(gè)批次(2條數(shù)據(jù)),直至全部處理完成。
大病項(xiàng)目案例:數(shù)據(jù)庫查詢1次查詢數(shù)量為1000條,在實(shí)際的邏輯處理中,我設(shè)置了本次批次處理的數(shù)據(jù)數(shù)量為500條,那一個(gè)批次就只處理500條,處理完第1個(gè)批次500條后,在處理下一次批次的500條。
注:
設(shè)計(jì)初衷:
為了讓大家都按照規(guī)范去做,因此抽象此接口,具體實(shí)現(xiàn)類去繼承,獲取對(duì)應(yīng)的實(shí)體對(duì)象,然后一一獲取里面的對(duì)象。
局限性:
當(dāng)在一個(gè)類中獲取的對(duì)象不只是一個(gè),此抽象接口不能使用,需要單獨(dú)的在自己的實(shí)現(xiàn)類中,按照此方式手寫對(duì)用的mapper,待補(bǔ)充
二、使用案例:
2.1. 自定義查詢接口
聲明接口作用:只是為了聽過一個(gè)接口供外部調(diào)用服務(wù)
package com.gblfy.ly.service;public interface ISDQueryResulService {public void batchSDHandle(); }
注:如果外部不需要調(diào)用,此接口可以省略,實(shí)現(xiàn)類可不實(shí)現(xiàn)此接口
2.2. 邏輯處理類
- 1>繼承extends SDQueryResultHandler重新handle方法,實(shí)現(xiàn)自己定義的接口
- 2>注入SDQueryWrapper接口
案例處理類路徑:
如下圖所示:
2.3. 調(diào)用案例
1.自定義SQL語句 2.new 本身邏輯處理類 3.設(shè)置具體處理的批次數(shù)據(jù)數(shù)量 4.把new 好的處理類變量名,放到此方法內(nèi)部 5.調(diào)用lastSDHandle方法注:具體使用請(qǐng)參考,案例代碼,已上傳gitlab倉庫2.4. 具體邏輯處理案例
聲明:查詢批次的結(jié)果集最終返回的數(shù)據(jù)是一個(gè)list,大家只需要對(duì)list中的數(shù)據(jù)進(jìn)行循環(huán)遍歷,根據(jù)key獲取處理對(duì)應(yīng)的value即可。
三、企業(yè)案例
參數(shù)獲取方式:根據(jù)key獲取value,簡言之,查詢出來的數(shù)據(jù)放到了map中。
3.1. key名稱獲取
所有的key和value就都展示了出來
如下圖所示:
3.2. 邏輯類測試
在com.gblfy.ly.service.impl. SDQueryResulServiceImpl類的35行打上斷點(diǎn),滿足一個(gè)批次的數(shù)量就會(huì)跳到handle此方法中
注:數(shù)據(jù)庫一共5條數(shù)據(jù)。
3.3.最后一個(gè)批次處理方案
從開始到結(jié)束,按照批次依次執(zhí)行到最后一個(gè)批次,會(huì)自動(dòng)調(diào)用lastSDHandle方法,因此,我們只需要處理好handle()方法即可。
最后,把獲取的數(shù)據(jù)進(jìn)行處理根據(jù)實(shí)際需求自行處理。
四、 通用SQL預(yù)編譯處理
4.1. 業(yè)務(wù)場景
相同SQL和數(shù)據(jù)庫交互多次,請(qǐng)按照規(guī)范適應(yīng)預(yù)編譯處理。
4.2. xml形式
在xml文件中添加statementType="PREPARED"即屬性可
4.3. 注解形式
statementType = StatementType.PREPARED五、企業(yè)案例
5.1. sql語句
-- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` (`id` bigint(20) NOT NULL COMMENT '主鍵ID',`name` varchar(30) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '姓名',`age` int(11) DEFAULT NULL COMMENT '年齡',`email` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '郵箱',PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;-- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES ('1', 'Jone', '18', 'test1@baomidou.com'); INSERT INTO `user` VALUES ('2', 'Jack', '20', 'test2@baomidou.com'); INSERT INTO `user` VALUES ('3', 'Tom', '28', 'test3@baomidou.com'); INSERT INTO `user` VALUES ('4', 'Sandy', '21', 'test4@baomidou.com'); INSERT INTO `user` VALUES ('5', 'Billie', '24', 'test5@baomidou.com');5.2. 大數(shù)據(jù)流查詢接口
package com.gblfy.ly.mapper;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; import com.gblfy.ly.entity.User; import org.apache.ibatis.annotations.*; import org.apache.ibatis.mapping.ResultSetType; import org.apache.ibatis.mapping.StatementType; import org.apache.ibatis.session.ResultHandler;import java.util.Map;/*** 處理流數(shù)據(jù)的公用接口** @author gblfy* @date 2020-11-18*/ @Mapper public interface SDQueryWrapper {/*** ResultSetType.FORWARD_ONLY 表示游標(biāo)只向前滾動(dòng)* fetchSize 每次查詢數(shù)量* @ResultTyp 定義返回的對(duì)象類型** @param sql SQL語句* @param handler 返回處理數(shù)據(jù)對(duì)象*/@Select("${sql}")@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000)@ResultType(Map.class)void streamDataDynamicHandle(@Param("sql") String sql, ResultHandler<Map> handler);@Select("${sql}")@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 2)@ResultType(User.class)void dynamicSelectLargeData1(@Param("sql") String sql, ResultHandler<User> handler);@Select("select * from user t ${ew.customSqlSegment}")@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000,statementType = StatementType.PREPARED)@ResultType(User.class)void getOrgWithBigData(@Param(Constants.WRAPPER) QueryWrapper<User> wrapper, ResultHandler<User> handler); }5.3. 大數(shù)據(jù)查詢結(jié)果集處理抽象類
package com.gblfy.ly.config;import org.apache.ibatis.session.ResultContext; import org.apache.ibatis.session.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory;import java.util.ArrayList; import java.util.List; import java.util.Map;/*** 大數(shù)據(jù)查詢結(jié)果集處理抽象類** @author gblfy* @date 2020-11-18*/ public abstract class SDQueryResultHandler implements ResultHandler<Map> {private final static Logger logger = LoggerFactory.getLogger(SDQueryResultHandler.class);// 這是每一個(gè)批處理查詢的數(shù)量public int batchSize = 1000;//初始值public int size=0;// 存儲(chǔ)每批數(shù)據(jù)的臨時(shí)容器public List<Map> list = new ArrayList<Map>();public void handleResult(ResultContext<? extends Map> resultContext) {// 這里獲取流式查詢每次返回的單條結(jié)果Map map = resultContext.getResultObject();list.add(map);size++;if (size == batchSize) {logger.info("本批次處理數(shù)據(jù)量 :{}",size );handle();}}// 1.這個(gè)方需要子類重寫此接口,處理具體業(yè)務(wù)邏輯public abstract void handle();//處理最后一批不到 batchSize(查詢?cè)O(shè)定的閥值)的數(shù)據(jù)public void lastSDHandle() {logger.info("最后批次處理數(shù)據(jù)量 :{}",size );handle();}public void setBatchSize(int batchSize) {this.batchSize = batchSize;} }5.4. 服務(wù)接口
package com.gblfy.ly.service;public interface ISDQueryResulService {public void batchSDHandle(); }5.5. 服務(wù)接口實(shí)現(xiàn)類
package com.gblfy.ly.service.impl;import com.gblfy.ly.config.SDQueryResultHandler; import com.gblfy.ly.mapper.SDQueryWrapper; import com.gblfy.ly.service.ISDQueryResulService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service;import javax.annotation.Resource;@Service public class SDQueryResulServiceImpl extends SDQueryResultHandler implements ISDQueryResulService {private final static Logger logger = LoggerFactory.getLogger(SDQueryResulServiceImpl.class);@Resourceprivate SDQueryWrapper sdQueryWrapper;@Overridepublic void batchSDHandle() {String sql = "select * from user";SDQueryResulServiceImpl sdQueryResulService = new SDQueryResulServiceImpl();sdQueryResulService.setBatchSize(2);//批量處理數(shù)據(jù)量 根據(jù)實(shí)際情況設(shè)置//1.按批次處理查詢結(jié)果集數(shù)據(jù)sdQueryWrapper.streamDataDynamicHandle(sql,sdQueryResulService);//2.處理最后一個(gè)批次的查詢結(jié)果數(shù)據(jù)sdQueryResulService.lastSDHandle();}// 在這里可以對(duì)你獲取到的批量結(jié)果數(shù)據(jù)進(jìn)行需要的業(yè)務(wù)處理@Overridepublic void handle() {try {logger.info("---------------------:{}",list.size());//list 批量查詢結(jié)果集,對(duì)此list進(jìn)行業(yè)務(wù)處理for (int i = 0; i < list.size(); i++) {logger.info("---------------------:{}",list.get(i).get("name"));}} finally {// 處理完每批數(shù)據(jù)后后將臨時(shí)清空size = 0;list.clear();}} }5.6. 前端控制器
package com.gblfy.ly.controller;import com.gblfy.ly.service.ISDQueryResulService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;@RestController public class SDQueryResultController {@Autowiredprivate ISDQueryResulService isdQueryResulService;@GetMapping("/batchSDHandle")public void batchSDHandle() {isdQueryResulService.batchSDHandle();} }總結(jié)
以上是生活随笔為你收集整理的Mybatis-plus 大数据量数据流式查询通用接口的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: rabbitmq 集群 ha负载 Con
- 下一篇: 关于java的取整/和取余%