文章目錄
MyBatis使用PageHelper排序分頁
前言
前面說明了:
本文說明如何使用PageHelper對查詢結果進行排序分頁。
排序分頁
排序分頁常用於列表展示,打開列表時會先根據默認排序進行排序,然後再對記錄進行分頁展示,包括顯示頁數、每頁顯示的記錄數和總記錄數。用戶可以選擇排序方式,查看第幾頁的內容,修改每頁可展示的記錄數。
根據排序分頁的實現,可以分爲客戶端排序分頁和服務端排序分頁。
- 客戶端排序分頁:也就是前端排序分頁,後端直接返回默認排序的全部數據,再由前端組件來進行排序分頁。客戶端排序分頁比較靈活,但是一般只用於數據量較少的情況。
- 服務端排序分頁:也就是後端排序分頁,後端在數據庫中執行
select count
來獲取總記錄數,並利用數據庫的特性進行分頁(比如MySQL的limit
和offset
)。服務端排序分頁性能較好,但是實現比較複雜。
PageHelper是MyBatis的服務端排序方式。
使用PageHelper排序分頁
添加PageHelper Spring Boot依賴
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.13</version>
</dependency>
新增一個列表查詢的方法
在UserMapper中新增一個列表查詢的方法:
List<User> listUsers(User user);
其對應的Mapper XML爲:
<select id="listUsers" parameterType="me.cookcode.springboot.mybatisdemo.model.User" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from t_user
where 1=1
<if test="name != null">
and `name` like concat('%', #{name,jdbcType=VARCHAR}, '%')
</if>
<if test="email != null">
and email like concat('%', #{email,jdbcType=VARCHAR}, '%')
</if>
</select>
- 該列表查詢支持根據name和email做模糊查詢,並返回全部符合條件的user
使用PageHelper來設置排序分頁查詢條件
從上面的Mapper XML中可以看到,SQL語句中並沒有select count
、limit
和order by
語句。這些排序分頁查詢條件都是通過PageHelper“動態注入”的。
PageHelper排序分頁示例:
@PostMapping("/users")
public ApiResponse getUsers(@RequestParam(value = "pageNum", defaultValue = "0") int pageNum,
@RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
@RequestParam(value = "orderBy", defaultValue = "name") String orderBy,
@RequestParam(value = "order", defaultValue = "asc") String order,
@RequestBody User user) {
// 設置pageSize最大值
if (pageSize > 50) {
pageSize = 50;
}
// 只允許指定的排序字段和排序方式,防止SQL注入
String[] orderByArr = {"name", "email"};
String orderByStr = "";
if (StringUtils.isNotEmpty(orderBy) && Arrays.asList(orderByArr).contains(orderBy.toLowerCase())) {
orderByStr = String.format("%s %s", orderBy.toLowerCase(), "asc".equalsIgnoreCase(order) ? "asc" : "desc");
} else {
// 默認排序
orderByStr = "name asc";
}
PageHelper.startPage(pageNum, pageSize, orderByStr);
List<User> users = userMapper.listUsers(user);
PageInfo<User> userPageInfo = new PageInfo<>(users);
return ApiResponse.success(userPageInfo);
}
爲了簡化自定義排序,也可以限制排序的種類,比如只支持“默認排序”、“播放多”、“新發布”和“彈幕多”,然後在Mapper XML中針對不同的排序種類來設定不同的
order by
來簡化排序,並防止SQL注入。
測試和查看日誌
假設已經安裝好IDEA的Restful Toolkit和MyBatis Log Plugin。
打開Tools / MyBatis Log Plugin可以查看到真正執行的排序分頁SQL日誌。
打開 View / Tools Windows / RestServices,就可以方便地對上面的REST API進行測試。
SQL日誌示例:
-- 查詢記錄總數
SELECT count(0)
FROM t_user
WHERE 1 = 1 AND `name` LIKE concat('%', '張', '%');
-- 查詢排序分頁記錄結果
SELECT id, `name`, email
FROM t_user
WHERE 1 = 1 AND `name` LIKE concat('%', '張', '%') order by name desc
LIMIT 2;
REST API返回的接口響應示例:
{
"code": 0,
"message": "OK",
"data": {
"total": 3,
"list": [
{
"id": 11,
"name": "張翠山",
"email": "[email protected]"
},
{
"id": 10,
"name": "張無忌",
"email": "[email protected]"
}
],
"pageNum": 1,
"pageSize": 2,
"size": 2,
"startRow": 1,
"endRow": 2,
"pages": 2,
"prePage": 0,
"nextPage": 2,
"isFirstPage": true,
"isLastPage": false,
"hasPreviousPage": false,
"hasNextPage": true,
"navigatePages": 8,
"navigatepageNums": [
1,
2
],
"navigateFirstPage": 1,
"navigateLastPage": 2
}
}