mybatis-plus是如何实现分页的
时间: 2025-07-09 12:42:48 浏览: 10
<think>嗯,我现在需要了解MyBatis-Plus是如何实现分页的。我之前用过MyBatis,知道它本身没有分页功能,需要自己写Limit或者用PageHelper这样的插件。MyBatis-Plus作为增强工具,应该在这方面有封装吧。
首先,我应该回忆一下MyBatis-Plus的基本用法。记得在配置类里可能会添加分页插件,比如PaginationInterceptor或者新的MybatisPlusInterceptor,对吗?可能不同版本有不同的配置方式。比如,旧版本用PaginationInterceptor,而新版本可能需要用MybatisPlusInterceptor,然后添加分页的插件进去。
然后,分页查询的时候,可能需要创建一个Page对象,传入当前页和每页大小。接着,调用Mapper的selectPage方法,或者Service层的page方法。这里可能需要用到IPage接口,Page是它的实现类。返回的结果会包含分页的数据和总条数等信息。
另外,分页的原理是什么?MyBatis-Plus应该是在底层自动生成了分页的SQL语句,比如MySQL的LIMIT。那它是如何拦截原来的SQL,然后进行改造的呢?可能通过插件机制,拦截执行的SQL,计算分页参数,然后拼接上LIMIT和OFFSET。同时,还会执行一个COUNT查询来获取总记录数。
对了,还要注意是否需要配置分页插件,如果不配置的话,分页可能不生效。比如,在Spring Boot项目中,需要在配置类里添加@Bean方法,注册分页插件。例如:
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
这样配置之后,才能使用分页功能。
另外,分页查询是否需要自定义XML或者可以使用Wrapper?好像大部分时候可以直接用selectPage方法,传入Page对象和Wrapper条件,而不需要写SQL。但如果复杂的查询可能需要自己写XML,但分页参数会自动处理。
可能还有一些细节,比如数据库类型不同的处理,比如Oracle的分页和MySQL的分页语法不同,MyBatis-Plus是如何适配的?应该是通过PaginationInnerInterceptor根据配置的数据库类型来生成不同的分页SQL。
那用户使用的时候,步骤大概是:
1. 配置分页插件。
2. 创建Page对象,设置当前页和大小。
3. 调用Mapper或Service的分页方法,传入Page和查询条件。
4. 处理返回的Page对象,获取数据和分页信息。
有没有可能自定义分页的SQL?比如在XML里写自己的查询语句,但参数使用Page,这时MyBatis-Plus会自动处理分页和总数量的查询。需要确保在XML中的查询id对应的方法参数包含Page类型,或者在接口方法返回IPage类型。
另外,分页查询的性能问题,当数据量大的时候,COUNT操作可能会慢,这时候有没有优化方法?比如,某些情况下可以跳过COUNT查询,或者自定义COUNT语句。
可能还要注意,当使用Wrapper时,分页的条件会被自动附加到查询中,同时COUNT语句也会应用同样的条件,以确保总数正确。
总结一下,MyBatis-Plus的分页实现主要依赖于分页插件拦截SQL,自动拼接分页语句,并执行COUNT查询,然后通过IPage对象返回结果。用户只需简单配置和调用方法即可,无需手动处理分页逻辑。</think>MyBatis-Plus 的分页功能通过 **插件拦截+自动SQL优化** 实现,以下是具体实现步骤和原理:
---
### 一、配置分页插件
需在Spring Boot配置类中注册分页拦截器(不同版本配置方式略有差异):
```java
@Configuration
public class MybatisPlusConfig {
// MyBatis-Plus 3.4+ 版本配置
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页拦截器,并指定数据库类型(如MySQL)
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
```
---
### 二、核心实现原理
1. **拦截SQL**
分页拦截器(`PaginationInnerInterceptor`)会拦截待执行的SQL语句。
2. **自动生成分页SQL**
根据当前数据库类型(如MySQL的`LIMIT`、Oracle的`ROWNUM`),在原SQL基础上动态拼接分页条件。
3. **执行COUNT查询**
自动生成并执行`SELECT COUNT(1)`语句,获取总记录数。
---
### 三、使用分页功能
#### 方式1:Mapper层直接调用
```java
// 创建分页参数:当前页=1,每页10条
Page<User> page = new Page<>(1, 10);
// 执行分页查询(可附加查询条件)
Page<User> result = userMapper.selectPage(page, null);
// 获取数据
List<User> users = result.getRecords(); // 当前页数据
long total = result.getTotal(); // 总记录数
```
#### 方式2:Service层调用
```java
// 使用Service的分页方法
IPage<User> page = userService.page(new Page<>(1, 10), Wrappers.<User>query().eq("age", 25));
```
---
### 四、自定义SQL分页
若需在XML中编写自定义SQL,只需满足以下条件:
1. 方法第一个参数为`Page<?>`类型
2. 返回值类型为`IPage<?>`
```xml
<!-- XML映射文件 -->
<select id="selectUserByPage" resultType="User">
SELECT * FROM user WHERE age > #{age}
</select>
```
```java
// Mapper接口
IPage<User> selectUserByPage(Page<User> page, @Param("age") Integer age);
// 调用方式
Page<User> pageParam = new Page<>(1, 10);
IPage<User> result = userMapper.selectUserByPage(pageParam, 18);
```
---
### 五、高级特性
1. **关闭COUNT查询**
```java
Page<User> page = new Page<>(1, 10).setSearchCount(false); // 不执行SELECT COUNT
```
2. **自定义COUNT语句**
在XML中定义`id="selectCustomPage_count"`的查询,拦截器会自动匹配。
3. **多租户/性能优化**
分页拦截器与其他拦截器(如租户拦截器)协同工作,确保SQL正确性。
---
### 六、注意事项
- **版本兼容性**:3.4+版本使用`MybatisPlusInterceptor`,旧版本用`PaginationInterceptor`。
- **性能问题**:大数据量表COUNT查询较慢,建议通过业务层缓存优化。
- **复杂SQL**:联表查询时需手动编写XML,但分页逻辑仍由插件自动处理。
通过上述机制,MyBatis-Plus 实现了简洁高效的分页功能,开发者只需关注业务逻辑,无需手动处理分页细节。
阅读全文
相关推荐


















