最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis-Plus進(jìn)行分頁查詢優(yōu)化的實(shí)踐指南

 更新時(shí)間:2025年07月10日 08:12:24   作者:碼農(nóng)阿豪@新空間  
在實(shí)際開發(fā)中,分頁查詢是常見的需求,尤其是需要關(guān)聯(lián)其他表獲取額外信息的場景,本文將介紹如何使用 MyBatis-Plus 進(jìn)行高效分頁查詢,并結(jié)合關(guān)聯(lián)查詢優(yōu)化數(shù)據(jù)填充,需要的可以了解下

1. 引言

在實(shí)際開發(fā)中,分頁查詢是常見的需求,尤其是需要關(guān)聯(lián)其他表獲取額外信息的場景。例如,在任務(wù)管理系統(tǒng)中,查詢?nèi)蝿?wù)列表時(shí),除了任務(wù)基本信息外,還需要顯示任務(wù)創(chuàng)建者的用戶名(通常存儲(chǔ)在用戶表中)。直接使用循環(huán)單條查詢會(huì)導(dǎo)致性能問題,而合理的優(yōu)化可以顯著提升查詢效率。

本文將介紹如何使用 MyBatis-Plus 進(jìn)行高效分頁查詢,并結(jié)合關(guān)聯(lián)查詢優(yōu)化數(shù)據(jù)填充,最終封裝成 VO(View Object) 返回給前端。我們將分析兩種優(yōu)化方案:

  • 單條查詢填充(適用于數(shù)據(jù)量較小的情況)
  • 批量查詢填充(適用于大數(shù)據(jù)量,提高性能)

2. 基礎(chǔ)分頁查詢實(shí)現(xiàn)

首先,我們回顧基礎(chǔ)的 MyBatis-Plus 分頁查詢實(shí)現(xiàn):

Page<TaskManagement> pageRequest = new Page<>(request.getPage(), request.getPageSize());

// 構(gòu)建查詢條件
LambdaQueryWrapper<TaskManagement> wrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotBlank(request.getStatus())) {
    wrapper.like(TaskManagement::getStatus, request.getStatus());
}

// 執(zhí)行分頁查詢
IPage<TaskManagement> taskManagementIPage = taskManagementService.page(pageRequest, wrapper);

這段代碼完成了:

  • 分頁參數(shù)構(gòu)建(Page 對象)
  • 動(dòng)態(tài)條件查詢(LambdaQueryWrapper
  • 執(zhí)行分頁查詢(taskManagementService.page()

但返回的數(shù)據(jù)僅包含 TaskManagement 表的信息,缺少關(guān)聯(lián)的用戶名(creatorUsername),我們需要進(jìn)一步優(yōu)化。

3. 優(yōu)化方案1:單條查詢填充(適用于小數(shù)據(jù)量)

3.1 定義VO對象

首先,定義一個(gè) TaskManagementVO,增加 creatorUsername 字段:

@Data
public class TaskManagementVO {
    private Long id;
    private String taskName;
    private String status;
    // 其他任務(wù)字段...
    
    private Long userId;       // 創(chuàng)建者ID
    private String creatorUsername; // 創(chuàng)建者姓名(需關(guān)聯(lián)用戶表查詢)
}

3.2 轉(zhuǎn)換分頁數(shù)據(jù)并填充用戶名

使用 IPage.convert() 方法進(jìn)行數(shù)據(jù)轉(zhuǎn)換,并在轉(zhuǎn)換過程中查詢用戶名:

IPage<TaskManagementVO> voPage = taskManagementIPage.convert(task -> {
    TaskManagementVO vo = new TaskManagementVO();
    BeanUtils.copyProperties(task, vo); // 使用Spring BeanUtils復(fù)制屬性
    
    if (task.getUserId() != null) {
        // 查詢用戶信息
        User user = userService.getById(task.getUserId());
        if (user != null) {
            vo.setCreatorUsername(user.getName());
        }
    }
    return vo;
});

return voPage;

3.3 優(yōu)缺點(diǎn)分析

優(yōu)點(diǎn):

  • 代碼簡單,易于理解
  • 適用于數(shù)據(jù)量較小的場景

缺點(diǎn):

  • N+1查詢問題:如果每頁有N條數(shù)據(jù),會(huì)額外執(zhí)行N次用戶查詢,性能較差
  • 不適合大數(shù)據(jù)量分頁

4. 優(yōu)化方案2:批量查詢填充(適用于大數(shù)據(jù)量)

4.1 優(yōu)化思路

  • 先收集所有 userId
  • 批量查詢用戶數(shù)據(jù),減少數(shù)據(jù)庫交互
  • 使用 Map 存儲(chǔ)用戶信息,提高查詢效率

4.2 代碼實(shí)現(xiàn)

// 1. 提取所有不重復(fù)的userId
List<Long> userIds = taskManagementIPage.getRecords().stream()
        .map(TaskManagement::getUserId)
        .filter(Objects::nonNull)
        .distinct()
        .collect(Collectors.toList());

// 2. 批量查詢用戶信息,并轉(zhuǎn)為Map<userId, User>
Map<Long, User> userMap = userIds.isEmpty() 
        ? Collections.emptyMap()
        : userService.listByIds(userIds).stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));

// 3. 轉(zhuǎn)換分頁數(shù)據(jù)并填充用戶名
IPage<TaskManagementVO> voPage = taskManagementIPage.convert(task -> {
    TaskManagementVO vo = new TaskManagementVO();
    BeanUtils.copyProperties(task, vo);
    
    if (task.getUserId() != null && userMap.containsKey(task.getUserId())) {
        vo.setCreatorUsername(userMap.get(task.getUserId()).getName());
    }
    return vo;
});

return voPage;

4.3 優(yōu)化點(diǎn)分析

優(yōu)點(diǎn):

  • 減少數(shù)據(jù)庫查詢次數(shù):無論分頁數(shù)據(jù)有多少條,用戶表只查詢1次
  • 性能更高:適合大數(shù)據(jù)量場景

缺點(diǎn):

  • 代碼稍復(fù)雜,需要額外處理 Map 結(jié)構(gòu)
  • 如果 userIds 過多(如 IN 查詢超過1000條),可能需要分批查詢

5. 進(jìn)一步優(yōu)化:使用JOIN查詢(SQL層面優(yōu)化)

如果 TaskManagementUser 表關(guān)聯(lián)頻繁,可以在 SQL 層面直接使用 JOIN 查詢,避免多次查詢:

5.1 自定義SQL查詢

<!-- TaskManagementMapper.xml -->
<select id="selectTaskPageWithUser" resultType="TaskManagementVO">
    SELECT 
        t.*,
        u.name AS creatorUsername
    FROM 
        task_management t
    LEFT JOIN 
        user u ON t.user_id = u.id
    <where>
        <if test="status != null and status != ''">
            t.status LIKE CONCAT('%', #{status}, '%')
        </if>
    </where>
</select>

5.2 在Service層調(diào)用

// 使用自定義分頁查詢
IPage<TaskManagementVO> voPage = taskManagementMapper.selectTaskPageWithUser(
        pageRequest, 
        request.getStatus());

5.3 優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  • 最高效:只需1次SQL查詢
  • 適合復(fù)雜關(guān)聯(lián)查詢

缺點(diǎn):

  • 需要手寫SQL,不夠靈活
  • 如果關(guān)聯(lián)表過多,SQL可能較復(fù)雜

6. 總結(jié)與最佳實(shí)踐

方案適用場景性能代碼復(fù)雜度
單條查詢填充數(shù)據(jù)量?。?lt;100條/頁)較差(N+1查詢)
批量查詢填充數(shù)據(jù)量較大(100-1000條/頁)較好(2次查詢)
JOIN查詢大數(shù)據(jù)量、頻繁關(guān)聯(lián)查詢最優(yōu)(1次查詢)高(需手寫SQL)

6.1 推薦選擇

  • 小型項(xiàng)目/簡單查詢 → 單條查詢填充
  • 中大型項(xiàng)目/數(shù)據(jù)量較大 → 批量查詢填充
  • 高性能要求/復(fù)雜關(guān)聯(lián) → JOIN查詢

6.2 完整優(yōu)化代碼示例

public IPage<TaskManagementVO> getTaskPage(TaskPageRequest request) {
    // 1. 構(gòu)建分頁查詢
    Page<TaskManagement> pageRequest = new Page<>(request.getPage(), request.getPageSize());
    LambdaQueryWrapper<TaskManagement> wrapper = new LambdaQueryWrapper<>();
    if (StringUtils.isNotBlank(request.getStatus())) {
        wrapper.like(TaskManagement::getStatus, request.getStatus());
    }
    
    // 2. 執(zhí)行分頁查詢
    IPage<TaskManagement> taskManagementIPage = taskManagementService.page(pageRequest, wrapper);
    
    // 3. 批量查詢用戶信息
    List<Long> userIds = taskManagementIPage.getRecords().stream()
            .map(TaskManagement::getUserId)
            .filter(Objects::nonNull)
            .distinct()
            .collect(Collectors.toList());
    
    Map<Long, User> userMap = userIds.isEmpty() 
            ? Collections.emptyMap()
            : userService.listByIds(userIds).stream()
                    .collect(Collectors.toMap(User::getId, Function.identity()));
    
    // 4. 轉(zhuǎn)換VO并填充用戶名
    return taskManagementIPage.convert(task -> {
        TaskManagementVO vo = new TaskManagementVO();
        BeanUtils.copyProperties(task, vo);
        
        if (task.getUserId() != null && userMap.containsKey(task.getUserId())) {
            vo.setCreatorUsername(userMap.get(task.getUserId()).getName());
        }
        return vo;
    });
}

7. 結(jié)語

優(yōu)化分頁查詢的核心在于 減少數(shù)據(jù)庫交互次數(shù),本文介紹了三種優(yōu)化方案,適用于不同場景。在實(shí)際開發(fā)中,應(yīng)根據(jù)業(yè)務(wù)需求和數(shù)據(jù)量選擇最合適的方案。

進(jìn)一步優(yōu)化建議:

  • 使用 緩存(Redis) 存儲(chǔ)用戶信息,減少數(shù)據(jù)庫查詢
  • 對于超大數(shù)據(jù)量(如10萬+),考慮 游標(biāo)分頁 或 Elasticsearch 優(yōu)化

到此這篇關(guān)于MyBatis-Plus進(jìn)行分頁查詢優(yōu)化的實(shí)踐指南的文章就介紹到這了,更多相關(guān)mybatis-plus分頁查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Springboot+Bootstrap實(shí)現(xiàn)增刪改查實(shí)戰(zhàn)

    Springboot+Bootstrap實(shí)現(xiàn)增刪改查實(shí)戰(zhàn)

    這篇文章主要介紹了Springboot+Bootstrap實(shí)現(xiàn)增刪改查實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 基于request獲取訪問者真實(shí)IP代碼示例

    基于request獲取訪問者真實(shí)IP代碼示例

    這篇文章主要介紹了基于request獲取訪問者真實(shí)IP代碼示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Spring TaskScheduler使用實(shí)例解析

    Spring TaskScheduler使用實(shí)例解析

    這篇文章主要介紹了Spring TaskScheduler使用實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • SpringBoot的單體和分布式的任務(wù)架構(gòu)詳解

    SpringBoot的單體和分布式的任務(wù)架構(gòu)詳解

    在Spring Boot生態(tài)中,定時(shí)任務(wù)框架的選擇需根據(jù)架構(gòu)類型(單體或分布式)和功能需求進(jìn)行權(quán)衡,以下從框架特性、適用場景及Spring Boot集成方式等角度,詳細(xì)梳理主流的定時(shí)任務(wù)框架及其分類,本文給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-05-05
  • Spring Boot 中的橫切邏輯統(tǒng)一治理方案

    Spring Boot 中的橫切邏輯統(tǒng)一治理方案

    攔截器是Spring框架提供的核心功能之一,核心用于統(tǒng)一攔截用戶的請求,文章主要介紹了Spring框架中的攔截器、統(tǒng)一數(shù)據(jù)返回格式和統(tǒng)一異常處理,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2026-02-02
  • Spring如何消除代碼中的if-else/switch-case

    Spring如何消除代碼中的if-else/switch-case

    這篇文章主要給大家介紹了關(guān)于Spring如何消除代碼中if-else/switch-case的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Spring具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java多線程run方法中直接調(diào)用service業(yè)務(wù)類應(yīng)注意的問題及解決

    Java多線程run方法中直接調(diào)用service業(yè)務(wù)類應(yīng)注意的問題及解決

    這篇文章主要介紹了Java多線程run方法中直接調(diào)用service業(yè)務(wù)類應(yīng)注意的問題及解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • java實(shí)現(xiàn)對map的字典序排序操作示例

    java實(shí)現(xiàn)對map的字典序排序操作示例

    這篇文章主要介紹了java實(shí)現(xiàn)對map的字典序排序操作,結(jié)合實(shí)例形式分析了java參照微信官網(wǎng)算法實(shí)現(xiàn)的字典序排序操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-07-07
  • Spring中事務(wù)幾個(gè)常見的問題解決

    Spring中事務(wù)幾個(gè)常見的問題解決

    這篇文章主要介紹了Spring中事務(wù)幾個(gè)常見的問題解決,事務(wù)這個(gè)概念是數(shù)據(jù)庫層面的,Spring只是基于數(shù)據(jù)庫中的事務(wù)進(jìn)行擴(kuò)展,以及提供了一些能讓程序員更新方便操作事務(wù)的方式
    2022-08-08
  • 一文盤點(diǎn)Spring MVC中用于處理HTTP請求的常用注解

    一文盤點(diǎn)Spring MVC中用于處理HTTP請求的常用注解

    這篇文章主要為大家詳細(xì)介紹了Spring MVC中用于處理HTTP請求的常用注解,包括@RequestMapping,@RequestController,@RequestParam等,希望對大家有所幫助
    2026-03-03

最新評論

射洪县| 镇原县| 琼中| 八宿县| 武鸣县| 环江| 龙南县| 上犹县| 门源| 寻乌县| 武平县| 永川市| 武功县| 丹巴县| 余庆县| 大名县| 南郑县| 天水市| 凤城市| 拜城县| 长治市| 方正县| 改则县| 乐昌市| 莲花县| 安吉县| 嫩江县| 明溪县| 合水县| 龙井市| 延川县| 察哈| 通渭县| 安庆市| 炉霍县| 西丰县| 江华| 新余市| 弥勒县| 襄汾县| 镇远县|