转载自:www.javaman.cn
目前主流的分页MyBatis-Plus 分页和PageHelper 分页,两者区别如下:
- 集成方式:
- MyBatis-Plus:通过内置的拦截器实现分页功能,需要添加分页插件的配置。
- PageHelper:通过 MyBatis 的拦截器实现分页,以插件的形式与 MyBatis 集成。
- 使用方式:
- MyBatis-Plus:调用内置方法进行分页查询,例如
page()
方法,需要传入分页参数。 - PageHelper:在查询之前调用
PageHelper.startPage()
方法,传入分页参数,然后执行正常的查询。
- 灵活性:
- MyBatis-Plus:提供了较多的分页相关配置选项,可以根据需求进行自定义配置。
- PageHelper:也提供了一些配置选项,但相对较少,可能不如 MyBatis-Plus 灵活。
- 性能:
- 两者在实现上类似,性能上的差异主要取决于具体的数据库和查询语句。一般来说,它们的性能差异不大。
- 社区支持与维护:
- MyBatis-Plus:作为 MyBatis 的增强工具包,拥有较大的用户群体和社区支持,并且持续维护更新。
- PageHelper:也拥有一定的用户群体和社区支持,但近年来更新较少。
- 其他特性:
- MyBatis-Plus:除了分页功能外,还提供了其他的一些便利功能,如 CRUD 操作、自动填充字段等。
- PageHelper:专注于分页功能,没有其他额外的特性。
总结:MyBatis-Plus 和 PageHelper 在分页功能上都相对成熟且易于使用。选择哪个主要取决于你的项目需求和个人偏好。如果你只需要专注于分页功能,并且对灵活性要求不高,那么 PageHelper 是一个不错的选择。如果你希望获得更多的特性和更好的社区支持,那么 MyBatis-Plus 可能更适合你。
今天我们主要介绍pagehelper分页
1、PageHelper简单例子
举个例子,假设有一个 User
表,需要进行分页查询并获取总记录数。在这种情况下,可以使用 PageHelper 插件来处理分页,并利用 count=countSql
参数来指定另外一条 SQL 查询来获取总记录数,而不是在每次分页查询时都重新查询全部数据进行计数。
假设有一个 UserMapper
接口和对应的 XML 映射文件:
public interface UserMapper {
List<User> getUsers(); // 分页查询用户列表
int countUsers(); // 获取用户总数
}
<!-- UserMapper.xml -->
<select id="getUsers" resultType="User">
SELECT * FROM users
</select>
<select id="countUsers" resultType="int">
SELECT COUNT(*) FROM users
</select>
使用 PageHelper 进行分页查询时,可以设置 count=countSql
参数来指定额外的 SQL 查询来获取总记录数:
PageHelper.startPage(pageNum, pageSize, "id desc", true, true); // 启动分页插件,并指定排序规则
List<User> users = userMapper.getUsers(); // 获取分页后的用户列表
int total = userMapper.countUsers(); // 获取总记录数,这里会执行额外的SQL查询获取总数
PageInfo<User> pageInfo = new PageInfo<>(users);
long totalElements = pageInfo.getTotal(); // 获取总记录数,也可以从PageInfo中获取
在这个例子中,使用 PageHelper.startPage()
开启分页查询,然后在分页查询之后,通过执行额外的 countUsers()
方法获取总记录数,而不是通过重新执行类似于分页查询的 SQL 获取总数。这样可以减少不必要的查询开销,提高分页查询的效率。
2、PageHelper实战
在上面例子中我们可以看到PageHelper.startPage
启动分页,PageInfo
得到分页数据,我们可以封装自己的结果对象,传到前台
@Data
public class TableDataInfo {
/** 总记录数 */
private long count;
/** 列表数据 */
private List<?> data;
/** 消息状态码 */
private int code;
}
添加pom.xml依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.version}</version>
</dependency>
添加pagehelper配置
pagehelper:
helper-dialect: mysql ##指定数据库方言
reasonable: true ##当设置为true时,PageHelper会使用一个更合理的算法来分页。默认情况下,如果你请求的页面超出了实际的总页数,它会返回最后一页的数据。但当你设置reasonable为true时,它会返回空数据
support-methods-arguments: true ##值为true时,PageHelper会支持通过Mapper接口方法参数来进行分页参数的传递。例如,你可以在Mapper方法中加入两个参数:(pageNum, pageSize),然后在实际调用时传入这两个值来实现分页。
params: count=countSql ##自定义SQL的参数配置。在这里,它定义了一个名为count的参数,并为其赋了一个值countSql。这意味着在执行分页查询时,它会使用名为countSql的SQL语句来获取总记录数
MyBatis-Plus 插件配置类
@Configuration
@MapperScan({"com.ds.blog.system.mapper","com.ds.blog.admin.mapper"})
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//添加分页插件
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return mybatisPlusInterceptor;
}
在上面例子中我们可以看到PageHelper.startPage
启动分页,PageInfo
得到分页数据,我们可以封装自己的结果对象,传到前台
@Data
public class TableDataInfo {
/** 总记录数 */
private long count;
/** 列表数据 */
private List<?> data;
/** 消息状态码 */
private int code;
}
BaseController
这段代码主要是一个基于Spring Boot框架的控制器(Controller)类,用于处理分页请求并返回分页数据。下面是代码的主要功能解释:
- BaseController类:
startPage()
方法:从HTTP请求中获取“page”和“limit”参数,并使用这些参数来配置分页。如果这些参数不存在,则会抛出异常。然后使用PageHelper.startPage(page, limit)
方法来实现分页。getDataTable(List<?> list)
方法:创建一个TableDataInfo
对象,设置其代码为0,将数据列表和总数设置到该对象中,并返回这个对象。这个方法主要用于包装查询到的分页数据。
- @GetMapping("/page")注解的方法:
- 这是一个处理GET请求的方法,映射路径为“/page”。
- 方法首先调用
startPage()
来设置分页参数。 - 然后,它使用
articleService.list()
方法来查询一个文章列表。查询条件包括:名字模糊匹配、频道ID精确匹配,并按orderNum
字段降序排列。 - 最后,它将查询到的文章列表包装到
TableDataInfo
对象中,并返回这个对象作为响应。
实现分页查询文章列表的功能,并返回包装后的分页数据。当客户端发送GET请求到“/page”路径时,服务器会根据请求中的分页参数来查询相应页码的文章数据,并将这些数据以及总数等信息返回给客户端。
创建一个BaseController,当调用查询的时候首先获取获取页数(page)和每页数据量(limit),将结果存入TableInfo,在前台展示
public class BaseController {
/**
* 设置请求分页数据
*/
public void startPage()
{
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
Assert.notNull(request.getParameter("page"), "page参数不存在");
Assert.notNull(request.getParameter("limit"), "limit参数不存在");
int page = Integer.parseInt(request.getParameter("page"));
int limit = Integer.parseInt(request.getParameter("limit"));
PageHelper.startPage(page, limit);
}
/**
* 响应请求分页数据
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected TableDataInfo getDataTable(List<?> list)
{
TableDataInfo tableDataInfo = new TableDataInfo();
tableDataInfo.setCode(0);
tableDataInfo.setData(list);
tableDataInfo.setCount(new PageInfo(list).getTotal());
return tableDataInfo;
}
}
业务Controller
@GetMapping("/page")
@ResponseBody
public TableDataInfo page(@Validated Article article) {
startPage();
List<Article> list = articleService.list(new LambdaQueryWrapper<Article>()
.like(StringUtils.isNotBlank(article.getName()), Article::getName, article.getName())
.eq(article.getChannelId()!=null,Article::getChannelId,article.getChannelId())
.orderByDesc(Article::getOrderNum));
return getDataTable(list);
}
前台页面接收
/ 查询列表接口
table.render({
elem: '#advertTable'
, toolbar: '#toolbar'
, height: 'full-110'
, url: ctx + '/blog/advert/page'
, cellMinWidth: 60
, page: true //开启分页
, cols: [[ //表头
{type: 'checkbox', fixed: 'left'},
{field: 'id', title: 'ID', hide: true},
{field: 'name', title: '广告名称'},
{field: 'orderNum', title: '排序'},
{
field: 'enabled', title: '是否启用', templet: function (d) {
if (d.enabled === 'Y') {
return '<span style="color: green;">启用</span>';
} else if (d.enabled === 'N') {
return '<span style="color: red;">禁用</span>';
} else {
return '';
}
}
},
{toolbar: '#tableBar', title: '操作', width: 300, align: 'center', fixed: 'right'}
]]
});