Spring Boot:实现MyBatis分页
综合概述
想必大家都有过这样的体验,在使用 Mybatis 时,最头痛的就是写分页了,需要先写一个查询 count 的 select 语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真的不想花双倍的时间写 count 和 select,幸好我们有 pagehelper 分页插件,pagehelper 是一个强大实用的 MyBatis 分页插件,可以帮助我们快速的实现 MyBatis 分页功能,而且 pagehelper 有个优点是,分页和 Mapper.xml 完全解耦,并以插件的形式实现,对 Mybatis 执行的流程进行了强化,这有效的避免了我们需要直接写分页 SQL 语句来实现分页功能。那么,接下来我们就来一起体验下吧。
实现案例
接下来,我们就通过实际案例来讲解如何使用 pagehelper 来实现 MyBatis 分页,为了避免重复篇幅,此篇教程的源码基于《Spring Boot:整合 MyBatis 框架》一篇的源码实现,读者请先参考并根据教程链接先行获取基础源码和数据库内容。
添加相关依赖
首先,我们需要在 pom.xml 文件中添加分页插件依赖包。
pom.xml
<!-- pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.5</version> </dependency>
添加相关配置
然后在 application.yml 配置文件中添加分页插件有关的配置。
application.yml
# pagehelper pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true params: count=countSql
编写分页代码
首先,在 DAO 层添加一个分页查找方法。这个查询方法跟查询全部数据的方法除了名称几乎一样。
SysUserMapper.java
package com.louis.springboot.demo.dao;import java.util.List;
import com.louis.springboot.demo.model.SysUser;public interface SysUserMapper {
int deleteByPrimaryKey(Long id);</span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> insert(SysUser record); </span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> insertSelective(SysUser record); SysUser selectByPrimaryKey(Long id); </span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> updateByPrimaryKeySelective(SysUser record); </span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> updateByPrimaryKey(SysUser record); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 查询全部用户 * </span><span style="color: rgba(128, 128, 128, 1)">@return</span> <span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> List</span><SysUser><span style="color: rgba(0, 0, 0, 1)"> selectAll(); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 分页查询用户 * </span><span style="color: rgba(128, 128, 128, 1)">@return</span> <span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> List</span><SysUser><span style="color: rgba(0, 0, 0, 1)"> selectPage();
}
然后在 SysUserMapper.xml 中加入 selectPage 的实现,当然你也可以直接用 @Select 注解将查询语句直接写在 DAO 代码,但我们这里选择写在 XML 映射文件,这是一个普通的查找全部记录的查询语句,并不需要写分页 SQL,分页插件会拦截查询请求,并读取前台传来的分页查询参数重新生成分页查询语句。
SysUserMapper.xml
<select id="selectPage" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from sys_user </select>
服务层通过调用 DAO 层代码完成分页查询,这里统一封装分页查询的请求和结果类,从而避免因为替换 ORM 框架而导致服务层、控制层的分页接口也需要变动的情况,替换 ORM 框架也不会影响服务层以上的分页接口,起到了解耦的作用。
SysUserService.java
package com.louis.springboot.demo.service; import java.util.List; import com.louis.springboot.demo.model.SysUser; import com.louis.springboot.demo.util.PageRequest; import com.louis.springboot.demo.util.PageResult;public interface SysUserService {
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 根据用户ID查找用户 * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> userId * </span><span style="color: rgba(128, 128, 128, 1)">@return</span> <span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> SysUser findByUserId(Long userId); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 查找所有用户 * </span><span style="color: rgba(128, 128, 128, 1)">@return</span> <span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> List</span><SysUser><span style="color: rgba(0, 0, 0, 1)"> findAll(); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 分页查询接口 * 这里统一封装了分页请求和结果,避免直接引入具体框架的分页对象, 如MyBatis或JPA的分页对象 * 从而避免因为替换ORM框架而导致服务层、控制层的分页接口也需要变动的情况,替换ORM框架也不会 * 影响服务层以上的分页接口,起到了解耦的作用 * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> pageRequest 自定义,统一分页查询请求 * </span><span style="color: rgba(128, 128, 128, 1)">@return</span><span style="color: rgba(0, 128, 0, 1)"> PageResult 自定义,统一分页查询结果 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> PageResult findPage(PageRequest pageRequest);
}
服务实现类通过调用分页插件完成最终的分页查询,关键代码是 PageHelper.startPage(pageNum, pageSize),将前台分页查询参数传入并拦截 MyBtis 执行实现分页效果。
SysUserServiceImpl.java
package com.louis.springboot.demo.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.louis.springboot.demo.dao.SysUserMapper; import com.louis.springboot.demo.model.SysUser; import com.louis.springboot.demo.service.SysUserService; import com.louis.springboot.demo.util.PageRequest; import com.louis.springboot.demo.util.PageResult; import com.louis.springboot.demo.util.PageUtils;@Service
public class SysUserServiceImpl implements SysUserService {@Autowired </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> SysUserMapper sysUserMapper; @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> SysUser findByUserId(Long userId) { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sysUserMapper.selectByPrimaryKey(userId); } @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span> List<SysUser><span style="color: rgba(0, 0, 0, 1)"> findAll() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sysUserMapper.selectAll(); } @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> PageResult findPage(PageRequest pageRequest) { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> PageUtils.getPageResult(pageRequest, getPageInfo(pageRequest)); } </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 调用分页插件完成分页 * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> pageQuery * </span><span style="color: rgba(128, 128, 128, 1)">@return</span> <span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">private</span> PageInfo<SysUser><span style="color: rgba(0, 0, 0, 1)"> getPageInfo(PageRequest pageRequest) { </span><span style="color: rgba(0, 0, 255, 1)">int</span> pageNum =<span style="color: rgba(0, 0, 0, 1)"> pageRequest.getPageNum(); </span><span style="color: rgba(0, 0, 255, 1)">int</span> pageSize =<span style="color: rgba(0, 0, 0, 1)"> pageRequest.getPageSize(); PageHelper.startPage(pageNum, pageSize); List</span><SysUser> sysMenus =<span style="color: rgba(0, 0, 0, 1)"> sysUserMapper.selectPage(); </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> PageInfo<SysUser><span style="color: rgba(0, 0, 0, 1)">(sysMenus); }
}
在控制器 SysUserController 中添加分页查询方法,并调用服务层的分页查询方法。
SysUserController.java
package com.louis.springboot.demo.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;import com.louis.springboot.demo.service.SysUserService;
import com.louis.springboot.demo.util.PageRequest;@RestController
@RequestMapping("user")
public class SysUserController {@Autowired </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> SysUserService sysUserService; @GetMapping(value</span>="/findByUserId"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Object findByUserId(@RequestParam Long userId) { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sysUserService.findByUserId(userId); } @GetMapping(value</span>="/findAll"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Object findAll() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sysUserService.findAll(); } @PostMapping(value</span>="/findPage"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Object findPage(@RequestBody PageRequest pageQuery) { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sysUserService.findPage(pageQuery); }
}
分页查询请求封装类。
PageRequest.java
package com.louis.springboot.demo.util; /** * 分页请求 */ public class PageRequest { /** * 当前页码 */ private int pageNum; /** * 每页数量 */ private int pageSize;</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> getPageNum() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> pageNum; } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> setPageNum(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> pageNum) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.pageNum =<span style="color: rgba(0, 0, 0, 1)"> pageNum; } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> getPageSize() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> pageSize; } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> setPageSize(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> pageSize) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.pageSize =<span style="color: rgba(0, 0, 0, 1)"> pageSize; }
}
分页查询结果封装类。
PageResult.java
package com.louis.springboot.demo.util; import java.util.List; /** * 分页返回结果 */ public class PageResult { /** * 当前页码 */ private int pageNum; /** * 每页数量 */ private int pageSize; /** * 记录总数 */ private long totalSize; /** * 页码总数 */ private int totalPages; /** * 数据模型 */ private List<?> content; public int getPageNum() { return pageNum; } public void setPageNum(int pageNum) { this.pageNum = pageNum; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public long getTotalSize() { return totalSize; } public void setTotalSize(long totalSize) { this.totalSize = totalSize; } public int getTotalPages() { return totalPages; } public void setTotalPages(int totalPages) { this.totalPages = totalPages; } public List<?> getContent() { return content; } public void setContent(List<?> content) { this.content = content; } }
分页查询相关工具类。
PageUtils.java
package com.louis.springboot.demo.util; import com.github.pagehelper.PageInfo;public class PageUtils {
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 将分页信息封装到统一的接口 * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> pageRequest * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> page * </span><span style="color: rgba(128, 128, 128, 1)">@return</span> <span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> PageResult getPageResult(PageRequest pageRequest, PageInfo<?><span style="color: rgba(0, 0, 0, 1)"> pageInfo) { PageResult pageResult </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PageResult(); pageResult.setPageNum(pageInfo.getPageNum()); pageResult.setPageSize(pageInfo.getPageSize()); pageResult.setTotalSize(pageInfo.getTotal()); pageResult.setTotalPages(pageInfo.getPages()); pageResult.setContent(pageInfo.getList()); </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> pageResult; }
}
编译测试运行
启动应用,访问:localhost:8088/swagger-ui.html,找到对应接口,模拟测试,结果如下。
参数:pageNum: 1, pageSize: 5
参数:pageNum: 2, pageSize: 4
胡言乱语
传统分页有点老,select 和 count 都得搞。
分页 SQL 写不好,内容耦合还不小。
pagehelper 帮你搞,使用起来有点屌。
参考资料
PageHelper:https://pagehelper.github.io/
PageHelper 手册:https://pagehelper.github.io/docs/howtouse/
相关导航
源码下载
码云:https://gitee.com/liuge1988/spring-boot-demo.git
作者:朝雨忆轻尘
出处:https://www.cnblogs.com/xifengxiaoma/
版权所有,欢迎转载,转载请注明原文作者及出处。