Implementing Multi-Table Pagination Queries with Spring Boot and MyBatis-Plus

Pagination Configuration Using MyBatis-Plus Built-in Support

package com.minster.yanapi.Config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

The configuration class declares a package, imports necessary MyBatis-Plus and Spring annotations, and defines a bean that returns a MybatisPlusInterceptor. The interceptor is configured with a PaginationInnerInterceptor set to MySQL data base type, enabling automatic pagination support.

Controller Layer Implementation

@GetMapping()
public ApiResponse<Page<ArticleResp>> getArticleList(@RequestParam("current") Integer current,
                                                     @RequestParam("pageSize") Integer pageSize) {
    Page<Map<String, Object>> page = new Page<>(current, pageSize);
    return yanArticleService.getArticleList(page);
}

The controller method handles GET requests without a specific path extension. It accepts two request parameters: current for the current page number and pageSize for the number of items per page. A Page object with Map<String, Object> type is created using these parameters, then passed to the service layer. The response is wrapped in an ApiResponse containing a Page<ArticleResp>.

Service Layer Transformation and Wrapping

public ApiResponse<Page<ArticleResp>> getArticleList(Page<Map<String, Object>> page) {
    Page<Map<String, Object>> result = yanArticleMapper.getArticleList(page);

    List<ArticleResp> yanArticles = result.getRecords().stream()
            .map(record -> {
                ArticleResp articleResp = new ArticleResp();
                articleResp.setId((Long) record.get("id"));
                articleResp.setTitle((String) record.get("title"));
                articleResp.setSummary((String) record.get("summary"));
                articleResp.setCreateTime((Date) record.get("createTime"));
                articleResp.setUsername((String) record.get("username"));
                articleResp.setAvatar((String) record.get("avatar"));
                articleResp.setLikeCount((Long) record.get("likeCount"));
                articleResp.setCommentCount((Long) record.get("commentCount"));
                return articleResp;
            })
            .collect(Collectors.toList());

    Page<ArticleResp> yanArticlePage = new Page<>();
    yanArticlePage.setRecords(yanArticles);
    yanArticlePage.setCurrent(result.getCurrent());
    yanArticlePage.setSize(result.getSize());
    yanArticlePage.setTotal(result.getTotal());
    yanArticlePage.setPages(result.getPages());
    return ApiResponse.success(yanArticlePage);
}

The service method receives a paginated query result from the mapper as Page<Map<String, Object>>. It converts each map record into an ArticleResp object using Java streams, extracting fields such as id, title, summary, createTime, username, avatar, likeCount, and commentCount. A new Page<ArticleResp> is constructed, populated with the transformed records and pagination metadata (current page, size, total, pages), then returned as a succsess response.

Mapper Layer with Custom SQL

@Select("SELECT\n" +
        "    a.id,\n" +
        "    a.title ,\n" +
        "    a.summary ,\n" +
        "    a.create_time AS createTime,\n" +
        "    u.username ,\n" +
        "    d.avatar, \n" +
        "    COUNT(DISTINCT c.id) AS likeCount ,\n" +
        "    COUNT(DISTINCT l.id) AS commentCount\n" +
        "FROM\n" +
        "    yan_article a\n" +
        "JOIN\n" +
        "    yan_user u ON a.author_id = u.id\n" +
        "LEFT JOIN\n" +
        "    yan_details d ON u.detail_id = d.id\n" +
        "LEFT JOIN\n" +
        "    yan_comment c ON a.id = c.article_id\n" +
        "LEFT JOIN\n" +
        "    yan_like l ON a.id = l.article_id\n" +
        "GROUP BY\n" +
        "    a.id, a.title, a.summary, a.create_time, u.username, d.avatar")
Page<Map<String, Object>> getArticleList(Page<Map<String, Object>> page);

The mapper method uses the @Select annotation with a custom SQL query. The query joins the yan_article table (alias a) with yan_user (u) and performs left joins on yan_details (d), yan_comment (c), and yan_like (l). It counts distinct comment IDs and like IDs to derive likeCount and commentCount. Results are grouped by article and user-related columns. The returned type is Page<Map<String, Object>>, where each map corresponds to a row with fields: id, title, summary, createTime, username, avatar, likeCount, commentCount.

Tags: Spring Boot mybatis-plus Pagination Multi-Table Query java

Posted on Sun, 26 Jul 2026 16:52:47 +0000 by catchy