Spring Boot整合MyBatis-Plus实现高效数据分页查询
组件依赖与环境准备
在构建Java后端服务时,若需快速落地分页逻辑,首选引入MyBatis-Plus官方启动器。该依赖内置了动态SQL解析与拦截器机制,无需额外编写底层游标处理代码。以下为Maven配置片段:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.5</version>
</dependency>
<!-- 关联对应数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
拦截器注册与方言适配
框架默认关闭分页拦截功能,必须通过配置类显式注入插件实例。新版本推荐采用独立Bean定义方式,并指明目标数据库方言以生成正确的Limit语法。
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 DbPluginRegistry {
@Bean
public MybatisPlusInterceptor initializePagination() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 锁定MySQL方言,自动转换分页语句
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
数据模型与持久层定义
实体类负责映射关系型表结构,Mapper接口继承基础抽象类即可获取内置方法。此处以员工档案表为例进行演示:
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("biz_staff")
public class StaffDO {
private Long workerId;
private String fullName;
private String workEmail;
private LocalDateTime entryTime;
}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface StaffRepository extends BaseMapper<StaffDO> {
// 基础CRUD已覆盖,复杂场景可在此扩展
}
业务层分页策略实施
实际开发中通常面临两种场景:简单条件过滤与多表关联查询。下面分别展示标准链式调用与自定义XML映射的实现路径。
隐式分页(基于BaseMapper)
直接利用框架提供的通用选择方法,传入分页对象与条件构造器即可。底层会自动执行Count查询与数据提取。
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class StaffBusinessService {
@Resource
private StaffRepository staffRepo;
public IPage<StaffDO> fetchStaffList(Integer currentPage, Integer rowLimit) {
// 初始化分页容器,索引默认从1开始
Page<StaffDO> queryContainer = new Page<>(currentPage, rowLimit);
// 附加过滤规则
LambdaQueryWrapper<StaffDO> filterChain = new LambdaQueryWrapper<>();
filterChain.like(StaffDO::getWorkEmail, "@example.com");
// 触发数据抓取
IPage<StaffDO> fetchedData = staffRepo.selectPage(queryContainer, filterChain);
return fetchedData;
}
}
显式分页(自定义SQL映射)
当涉及联合查询或窗口函数时,需编写专属SQL文件。注意第一个参数必须为分页对象,框架会替换原有SELECT语句并追加Limit子句。
// Repository接口定义
public interface StaffRepository extends BaseMapper<StaffDO> {
IPage<StaffDO> getFilteredStaff(Page<StaffDO> pageParam, String departmentCode);
}
<!-- resources/mapper/StaffRepository.xml -->
<mapper namespace="com.demo.repo.StaffRepository">
<select id="getFilteredStaff" resultType="com.demo.model.StaffDO">
SELECT worker_id, full_name, work_email, entry_time
FROM biz_staff
WHERE dept_code = #{departmentCode}
ORDER BY entry_time DESC
</select>
</mapper>
// 业务层调用示意
public IPage<StaffDO> loadDepartedStaff(String targetDept) {
Page<StaffDO> pageReq = new Page<>(1, 20);
return staffRepo.getFilteredStaff(pageReq, targetDept);
}
控制层暴露与参数校验
RESTful接口接收前端传参,并透传给Service层。框架会自动将返回的分页封装体序列化为JSON响应。
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("/api/v1/hr")
public class PersonnelController {
@Resource
private StaffBusinessService hrService;
@GetMapping("/roster")
public IPage<StaffDO> queryEmployeePage(
@RequestParam(name = "p", defaultValue = "1") Integer pageNum,
@RequestParam(name = "sz", defaultValue = "15") Integer pageSize) {
return hrService.fetchStaffList(pageNum, pageSize);
}
}
关键注意事项排查
- 插件未生效:检查配置文件是否遗漏@Bean注解,或拦截器加载顺序被其他AOP组件覆盖。
- Count统计异常:自定义XML中切勿硬编码LIMIT关键字,否则会导致重复截取或语法报错。
- 内存溢出风险:严禁使用超大分页容量(如每页10万条),建议配合索引优化或限制单次查询上限。
- 字段映射差异:数据库驼峰命名与Java属性不一致时,需在YAML开启map-underscore-to-camel-case配置,或在实体添加@TableField注解。
通过上述拦截器机制与标准API组合,开发者可将原本繁琐的SQL拼接工作交由框架代理。无论是单表检索还是复杂报表导出,均能保持代码整洁并降低维护成本。合理运用IPage元数据辅助前端UI渲染,可实现完整的流式数据体验。