Mybatis 分页查询

本文将介绍如何如何在 Java 中进行分页查询。

一、LIMIT

1. LIMIT

LIMIT 可以用于从返回结果中筛选指定部分的数据。

用法如下:

1
SELECT * FROM 表名 LIMIT [index], number

其中,

  • index:索引,表示返回结果中第一条记录的索引值

    从 0 开始计算

  • number:个数,表示返回的记录个数

  • 如果填入两个参数,则第一个参数为 index,第二个参数为number;

    如果填入一个参数,则 index 默认为 0,即从第一个开始,传入参数为 number

假设有记录如图所示:

1
SELECT * FROM 表名 LIMIT 1, 3

1
SELECT * FROM 表名 LIMIT 0, 2

1
SELECT * FROM 表名 LIMIT 2

2. SQL 中的 LIMIT

1
SELECT * FROM 表名 LIMIT (当前页数 - 1) * 每页条数, 每页条数

3. Mybatis 中使用 LIMIT

抽象方法:

1
List<User> getUserListByLimit(Map<String, Integer> map);

映射配置:

1
2
3
<select id="getUserListByLimit" parameterType="map" resultType="pojo.User">
select * from user limit #{index}, #{pageSize}
</select>

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 获取 sqlSession 对象
sqlSession = MyBatisUtils.getSqlSession();

// 获取 mapper 实例
mapper = sqlSession.getMapper(UserMapper.class);

// 创建 Map 实例,在其中放入参数
HashMap<String, Integer> map = new HashMap<>();
map.put("index", (2 - 1) * 2);
map.put("pageSize", 2);

// 调用方法,传入参数,执行 SQL
List<User> userList = mapper.getUserListByLimit(map);
for (User user : userList) {
System.out.println(user);
}

// 关闭 sqlSession
sqlSession.close();

执行结果:

二、物理分页和逻辑分页

  • 物理分页的做法是:根据要求向数据库查询指定的数据;

    逻辑分页的做法是:查询全部结果,放入内存中,截取指定的部分返回

  • 物理分页通过数据库语句实现(例如 SQL 中的 LIMIT);

    逻辑分页通过 Java 代码实现

  • 物理分页每次都要访问数据库,对数据库负担较大;

    逻辑分页只需要访问一次数据库

  • 物理分页占内存较小;

    逻辑分页一次性读取所有数据,因此需要占用较大的内存空间

  • 物理分页每次都访问数据库,因此实时性较强;

    逻辑分页将数据保存在内存中,无法保证数据的时效性

  • 物理分页适用于数据量较大、更新频繁的场合;

    逻辑分页适用于数据量较小、数据稳定的场合

三、RowBounds

不推荐使用

RowBounds 是逻辑分页,查询全部结果,截取指定的部分返回

抽象方法:

1
List<User> getUserListByRowBounds();

映射配置:

1
2
3
<select id="getUserListByRowBounds"resultType="pojo.User">
select * from user
</select>

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 获取 sqlSession 对象
sqlSession = MyBatisUtils.getSqlSession();

// 创建 RouwBounds 实例,传入偏移量和页面数据个数
RouwBounds rouwBounds = new RouwBounds(index, pageSize)

// 调用方法,执行 SQL,传入 RouwBounds 实例
List<User> userList = sqlSession.selectList("XxxMapper全限定类名.getUserListByRowBounds", null, rouwBounds)

for (User user : userList) {
System.out.println(user);
}

// 关闭 sqlSession
sqlSession.close();

四、PageHelper

PageHelper 是逻辑分页,根据要求向数据库查询指定的数据

1. 什么是 PageHelper ?

MyBatis 分页插件 PageHelper

PageHelper 是 MyBatis 的一款分页插件。

2. 集成

(1) 引入

在 pom.xml 中添加如下依赖:

1
2
3
4
5
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>版本号</version>
</dependency>

(2) 配置

法 1:

修改 Mybatis 配置文件 (mybatis-config.xml) 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
···
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 配置参数 -->
<property name="param1" value="value1"/>
<property name="param2" value="value2"/>
<property name="param3" value="value3"/>
</plugin>
</plugins>
···
</configuration>

法 2:

修改 Spring 配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!-- 配置参数 -->
<value>param1=value1</value>
<value>param2=value2</value>
<value>param3=value3</value>
</property>
</bean>
</array>
</property>
</bean>

</beans>

参数:

详见 如何使用分页插件

3. 简单集成

在 SpringBoot 中可以使用 pagehelper-spring-boot-starter 来更方便地集成 PageHelper。

(1) 引入

在 pom.xml 中添加如下依赖:

1
2
3
4
5
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>版本号</version>
</dependency>

(2) 配置

在 application.yml 中增加配置信息如下:

1
2
3
4
pagehelper:
helperDialect: mysql # 指定当前连接的数据库
reasonable: true # 纠错机制,pageNum<=0时查询第一页,pageNum超大时查询最后一页
supportMethodsArguments: true # 支持通过mapper的参数来传递分页参数

详见 如何使用分页插件

4. 使用方式 1

在 Service 中调用 mapper 的查询方法之前执行 PageHelper 的 startPage 方法:

需要注意的是:

有且仅有紧跟在 PageHelper 的 startPage 方法之后的第一个 Mybatis 查询方法才会被分页。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public class XxxServiceImpl implements XxxService {

···

@Override
public List<Xxx> getAllXxx() {
PageHelper.startPage([pageNum], [pageSize]);
return XxxMapper.getAllXxx();
}

···
}

5. 使用方式 2

为 Mapper 中的查询方法增加参数:pageNum 和 pageSize,PageHelper 会自动读取参数并进行分页。

如果需要更改参数名,可以通过 params 配置实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Mapper
public interface XxxMapper {

/**
* 查询所有
*/
List<Xxx> getAllXxx();

/**
* 查询所有,分页
*/
List<Xxx> getAllXxx(int pageNum, int pageSize);

}

参考