Java案例如何整合分页插件?

wen java案例 37

本文目录导读:

Java案例如何整合分页插件?

  1. 核心思路
  2. 环境准备
  3. 配置分页插件
  4. Service 层使用
  5. Controller 层调用
  6. 前端返回的 JSON 示例
  7. 重要注意事项

在Java开发中,整合分页插件最常用的场景是 MyBatis 搭配 PageHelper(一个非常流行的分页插件),以下是一个标准的整合案例。

核心思路

PageHelper 的工作原理是基于 MyBatis 的拦截器(Interceptor),在执行 SQL 查询之前,自动拦截并动态拼接上 LIMIT 分页语句,同时自动查询总记录数。

环境准备

假设你使用的是 Spring Boot + MyBatis 项目。

添加 Maven 依赖(pom.xml

<!-- MyBatis 启动器 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>
<!-- PageHelper 分页插件 -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>2.1.0</version> <!-- 注意版本兼容 -->
</dependency>

配置分页插件

Spring Boot 自动配置(推荐)

application.ymlapplication.properties 中配置:

pagehelper:
  helper-dialect: mysql           # 数据库方言(自动识别或指定)
  reasonable: true                # 启用合理化分页(页码<=0时查第一页,>总页数时查最后一页)
  supportMethodsArguments: true   # 支持通过 Mapper 接口参数来传递分页参数
  params: count=countSql         # 从参数中获取 count 查询的 SQL

Java 配置类(手动配置)

如果不想用 starter,可以通过 @Configuration 手动注入:

@Configuration
public class MyBatisConfig {
    @Bean
    public PageInterceptor pageInterceptor() {
        PageInterceptor interceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("helperDialect", "mysql");
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        interceptor.setProperties(properties);
        return interceptor;
    }
}

Service 层使用

分页插件的核心用法是在 查询之前 调用 PageHelper.startPage()

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    /**
     * 分页查询用户
     * @param pageNum  当前页码(从1开始)
     * @param pageSize 每页条数
     * @return PageInfo 包含了分页信息和数据
     */
    public PageInfo<User> findUsersByPage(int pageNum, int pageSize) {
        // 1. 设置分页参数(必须放在查询语句之前)
        PageHelper.startPage(pageNum, pageSize);
        // 2. 执行正常的查询(PageHelper会自动拦截并拼接 limit 语句)
        List<User> userList = userMapper.findAllUsers();
        // 3. 将查询结果封装成 PageInfo 对象
        //    PageInfo 包含了:当前页数据、总记录数、总页数、是否有下一页等信息
        return new PageInfo<>(userList);
    }
}

Controller 层调用

@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/page")
    public Result<PageInfo<User>> getUsersByPage(
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize) {
        PageInfo<User> pageInfo = userService.findUsersByPage(pageNum, pageSize);
        return Result.success(pageInfo);
    }
}

前端返回的 JSON 示例

PageInfo 对象序列化后,前端会得到如下结构:

{
  "pageNum": 1,
  "pageSize": 10,
  "total": 85,           // 总记录数
  "pages": 9,            // 总页数
  "list": [              // 当前页数据
    { "id": 1, "name": "张三" },
    { "id": 2, "name": "李四" }
  ],
  "isFirstPage": true,
  "isLastPage": false,
  "hasPreviousPage": false,
  "hasNextPage": true
}

重要注意事项

  1. 线程安全PageHelper.startPage() 使用 ThreadLocal,分页参数与当前线程绑定。必须保证在同一个线程中,且查询之后立即使用,不能跨方法或跨线程。

  2. 仅对紧随其后的第一个查询生效

    // 正确
    PageHelper.startPage(1, 10);
    List<User> list = userMapper.selectAll(); // 这个查询会被分页
    // 错误(中间不能有其它查询)
    PageHelper.startPage(1, 10);
    userMapper.countAll();  // 这个查询也会被分页,导致数据错乱
    List<User> list = userMapper.selectAll(); // 这个不会被分页
  3. 嵌套查询:Mapper 方法中包含 @Select 或 XML 中的 <association> 等嵌套查询,分页插件可能无法正确处理总条数,建议避免使用嵌套查询进行分页。

  4. 性能:分页插件会自动生成 count 查询(SELECT count(0) FROM ...),如果表数据量极大,count 查询本身可能会比较慢,可考虑使用其他优化方案(如缓存总条数)。

  • 加依赖pagehelper-spring-boot-starter
  • 配属性application.yml 中配置数据库方言
  • 写代码:在 Service 方法中,查询前调用 PageHelper.startPage(pageNum, pageSize),查询后使用 new PageInfo<>(list) 获取分页结果

这是目前 Java 后端最主流、最简洁的分页插件整合方式。

抱歉,评论功能暂时关闭!