25. MyBatis中的RowBounds是什么?如何实现内存分页?12. 如何在MyBatis中进行分页查询?常见的分页实现方式有哪些?
是 MyBatis 提供的一种用于结果集分页的功能,主要通过内存分页的方式实现。它通过在查询时传递分页参数,限制返回的结果集的大小。RowBounds 并不依赖于数据库层的分页功能,而是通过 MyBatis 在内存中对结果集进行截取,从而实现分页。
RowBounds 的基本属性
-
offset:从结果集的第几条记录开始截取。 -
limit:截取的记录条数。
例如,offset=5,limit=10 的 RowBounds 实例表示从结果集的第 6 条记录开始,取 10 条记录。
如何在 MyBatis 中使用 RowBounds 实现内存分页?
1. 使用 RowBounds 进行内存分页
RowBounds 的使用非常简单,可以通过 SqlSession 的 selectList 方法来传递 RowBounds 实例,从而实现分页。
示例:
假设我们有一个数据库表 user,并希望对查询结果进行分页。
Step 1: 定义 Mapper 接口
-
public interface UserMapper {
-
List<User> selectAllUsers(RowBounds rowBounds);
-
}
Step 2: 配置 XML 映射文件
-
<mapper namespace="com.example.mapper.UserMapper">
-
<select id="selectAllUsers" resultType="User">
-
SELECT * FROM user
-
</select>
-
</mapper>
Step 3: 使用 RowBounds 实现分页查询
-
try (SqlSession session = sqlSessionFactory.openSession()) {
-
UserMapper mapper = session.getMapper(UserMapper.class);
-
-
// 分页参数:从第 10 条记录开始,取 10 条记录
-
RowBounds rowBounds = new RowBounds(10, 10);
-
-
List<User> users = mapper.selectAllUsers(rowBounds);
-
-
users.forEach(System.out::println);
-
}
在这个例子中,RowBounds 实例被传递给 selectAllUsers 方法。RowBounds 将从查询结果的第 11 条记录开始,取 10 条记录进行返回。
2. RowBounds 的局限性
尽管 RowBounds 实现了分页功能,但它有一些局限性:
-
内存分页:
RowBounds是在内存中对查询结果进行分页,这意味着在数据库层面,查询仍然会返回完整的结果集。如果结果集非常大(比如包含数百万条记录),则会消耗大量的内存和处理时间,不适用于大数据量分页。 -
性能问题:由于
RowBounds是在内存中截取结果集,这对内存和 CPU 的消耗较大,尤其是当offset较大时,查询性能会显著下降。
如何实现数据库层面的分页(推荐)?
由于 RowBounds 的局限性,通常更推荐在数据库层面进行分页查询。不同的数据库支持不同的分页查询语法,以下是几种常见数据库的分页实现方式。
1. MySQL
在 MySQL 中,可以通过 LIMIT 子句实现分页:
SELECT * FROM user LIMIT #{offset}, #{limit};
MyBatis 配置:
-
<select id="selectUsersWithPagination" resultType="User">
-
SELECT * FROM user LIMIT #{offset}, #{limit}
-
</select>
Mapper 接口:
-
public interface UserMapper {
-
List<User> selectUsersWithPagination( int offset, int limit);
-
}
调用:
-
try (SqlSession session = sqlSessionFactory.openSession()) {
-
UserMapper mapper = session.getMapper(UserMapper.class);
-
List<User> users = mapper.selectUsersWithPagination(10, 10);
-
users.forEach(System.out::println);
-
}
2. Oracle
在 Oracle 中,可以通过 ROWNUM 或者 ROW_NUMBER() 函数实现分页:
-
SELECT * FROM (
-
SELECT t.*, ROWNUM r FROM (SELECT * FROM user ORDER BY id) t WHERE ROWNUM <= #{end}
-
) WHERE r > #{start};
MyBatis 配置:
-
<select id="selectUsersWithPagination" resultType="User">
-
SELECT * FROM (
-
SELECT t.*, ROWNUM r FROM (SELECT * FROM user ORDER BY id) t WHERE ROWNUM <= #{end}
-
) WHERE r > #{start}
-
</select>
Mapper 接口:
-
public interface UserMapper {
-
List<User> selectUsersWithPagination( int start, int end);
-
}
调用:
-
try (SqlSession session = sqlSessionFactory.openSession()) {
-
UserMapper mapper = session.getMapper(UserMapper.class);
-
List<User> users = mapper.selectUsersWithPagination(10, 20); // 从第11到20条
-
users.forEach(System.out::println);
-
}
3. PostgreSQL
在 PostgreSQL 中,使用 LIMIT 和 OFFSET 进行分页:
SELECT * FROM user LIMIT #{limit} OFFSET #{offset};
MyBatis 配置和调用方式与 MySQL 类似。
总结
-
RowBounds的用途:RowBounds是 MyBatis 提供的一种内存分页方式,适用于小数据量的分页场景。 -
局限性:由于
RowBounds是在内存中截取结果集,对于大数据量分页会带来性能问题和内存消耗,通常不推荐在大数据量情况下使用。 -
推荐的分页方式:通常推荐在数据库层面进行分页,通过 SQL 的
LIMIT或OFFSET等子句直接获取分页后的结果集,这样可以有效减少数据传输和内存占用,提高分页性能。
在实际开发中,根据数据量大小和系统性能要求选择合适的分页方式。
在MyBatis中,分页查询是一种常见的需求,尤其是在处理大数据量的情况下。MyBatis本身不直接提供分页功能,但可以通过以下几种常见的实现方式来实现分页查询。
1. 手动分页
这是最基本的分页方式,直接在SQL语句中添加分页参数。不同的数据库分页语法不同,以下是一些常见数据库的分页实现。
1.1 MySQL中的分页
-
<select id="findUsersByPage" resultType="User">
-
SELECT * FROM users
-
LIMIT #{offset}, #{pageSize}
-
</select>
-
LIMIT #{offset}, #{pageSize}:offset表示起始行偏移量,pageSize表示每页的记录数。
1.2 Oracle中的分页
-
<select id="findUsersByPage" resultType="User">
-
SELECT * FROM (
-
SELECT A.*, ROWNUM AS RN
-
FROM (SELECT * FROM users ORDER BY id) A
-
WHERE ROWNUM <= #{endRow}
-
)
-
WHERE RN > #{startRow}
-
</select>
-
Oracle使用ROWNUM来实现分页,其中
startRow和endRow分别表示分页的起始和结束行号。
1.3 SQL Server中的分页
-
<select id="findUsersByPage" resultType="User">
-
SELECT * FROM (
-
SELECT ROW_NUMBER() OVER (ORDER BY id) AS RowNum, *
-
FROM users
-
) AS result
-
WHERE RowNum BETWEEN #{startRow} AND #{endRow}
-
</select>
-
SQL Server中,使用ROW_NUMBER()函数进行分页,并结合
BETWEEN语句来筛选行号范围。
2. 使用RowBounds对象进行分页
MyBatis提供了RowBounds对象用于内存分页。它会将查询结果集限制在指定的行数内。这种方式不依赖于数据库的分页语法,而是通过Java内存进行分页。
2.1 使用RowBounds分页
-
List<User> findUsers(RowBounds rowBounds);
-
java复制代码RowBounds rowBounds = new RowBounds(offset, pageSize);
-
List<User> users = userMapper.findUsers(rowBounds);
-
RowBounds通过offset和limit进行分页。
2.2 注意事项
-
RowBounds会将查询的所有结果集加载到内存中,然后进行分页处理,这对大数据量查询效率较低,适合小数据量分页场景。
3. 使用分页插件
分页插件是一种更为高效和方便的方式,特别是在大型项目中。分页插件会自动拦截查询SQL,并在其基础上增加分页逻辑。
3.1 MyBatis-PageHelper插件
PageHelper是MyBatis的一个常用分页插件,它通过拦截SQL语句并追加分页语句来实现分页查询。
-
Maven依赖:
-
<dependency>
-
<groupId>com.github.pagehelper</groupId>
-
<artifactId>pagehelper</artifactId>
-
<version>5.2.0</version>
-
</dependency>
-
-
配置方式:
-
-
public class MyBatisConfig {
-
-
public PageHelper pageHelper() {
-
PageHelper pageHelper = new PageHelper();
-
Properties properties = new Properties();
-
properties.setProperty("helperDialect", "mysql");
-
properties.setProperty("reasonable", "true");
-
properties.setProperty("supportMethodsArguments", "true");
-
pageHelper.setProperties(properties);
-
return pageHelper;
-
}
-
}
-
-
使用方式:
-
PageHelper.startPage(pageNum, pageSize);
-
List<User> users = userMapper.findAll();
-
PageInfo<User> pageInfo = new PageInfo<>(users);
-
PageHelper.startPage(pageNum, pageSize):设置分页参数,pageNum表示当前页码,pageSize表示每页显示的记录数。 -
PageInfo<User>:PageInfo是一个分页结果对象,包含了分页后的信息,如总页数、总记录数等。
-
3.2 MyBatis-Plus中的分页插件
MyBatis-Plus也提供了分页插件,使用方式类似于PageHelper。
-
Maven依赖:
-
<dependency>
-
<groupId>com.baomidou</groupId>
-
<artifactId>mybatis-plus-boot-starter</artifactId>
-
<version>3.4.3.4</version>
-
</dependency>
-
-
配置方式:
-
-
public class MyBatisPlusConfig {
-
-
public MybatisPlusInterceptor mybatisPlusInterceptor() {
-
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
-
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
-
return interceptor;
-
}
-
}
-
-
使用方式:
-
Page<User> page = new Page<>(pageNum, pageSize);
-
IPage<User> userPage = userMapper.selectPage(page, null);
-
Page<>(pageNum, pageSize):构建分页参数对象。 -
IPage<User>:MyBatis-Plus中的分页结果对象,包含分页后的数据和分页信息。
-
4. 数据库支持的分页查询
有些数据库(如MySQL、PostgreSQL)天生支持分页查询,可以直接在SQL语句中使用LIMIT、OFFSET等关键字进行分页,而其他数据库(如Oracle)则需要使用子查询或窗口函数来实现分页。
总结
在MyBatis中实现分页查询的方式主要有以下几种:
-
手动分页:直接在SQL中编写分页语句,适合于需要控制分页SQL的场景,但需要根据不同数据库编写不同的分页SQL。
-
RowBounds分页:MyBatis提供的内存分页方法,适合小数据量分页,但不推荐大数据量使用。 -
分页插件:如PageHelper、MyBatis-Plus分页插件,通过拦截器方式实现分页,自动生成分页SQL,适合大多数场景,性能较好。
选择哪种分页方式应根据项目的实际需求、数据量大小以及开发的复杂性进行权衡。对于大多数场景,使用分页插件是一个简单高效的选择。

浙公网安备 33010602011771号