文章目录
- MyBatis 分页插件 PageHelper-Dazer007
- 1、使用方式
- 1.1 原始PageHelper
- 1.2 ruoyi框架封装PageHelper
- 1.3 MyBaits-Plus自带分页,无需PageHeler
- 2、作用原理
- 3、数据方言实现
- 3.1、MySqlDialect
- 3.2、OracleDialect
- 3.3、SqlServer2012Dialect
- 3、数据方言实现
MyBatis作为目前流行的ORM框架,大大方便了日常开发。而对于分页查询,虽然可以通过SQL的limit语句实现,但是比较繁琐。而MyBatis PageHelper的出现,则解决了这一痛点。
参考1-腾讯云:Mybatis分页插件: pageHelper的使用及其原理解析、
参考2-官网-认真阅读:https://pagehelper.github.io/docs/howtouse/、
参考3-知乎:MyBatis之分页查询:MyBatis PageHelpe
MyBatis 分页插件 PageHelper-Dazer007
1、使用方式
PageHelper是一个物理分页的插件,根据Sql方言,执行不同的分页方法,可以放到service或者mapper查询之前,但是只对第一个查询有效;
1.1 原始PageHelper
//使用原始的PageHelper分页方法
//PageHelper必须紧跟service 或者 mapper,只对代码后面的第一个查询有效,切记
PageHelper.startPage(pageNum, pageSize);
List<VficWxSubscribeMsg> data = vficWxSubscribeMsgMapper.getCurrentRecommendMsg();
1.2 ruoyi框架封装PageHelper
//2020-2023涉疫项目若依(hesuan、yimiao)中大量使用了BaseController若依PageHelper封装的分页
this.startPage();
List<PreCheckDTO> list = queryService.getPreCheckList(vo);
return this.getDataTable(list);
1.3 MyBaits-Plus自带分页,无需PageHeler
//lflk、zyt、jhmy中全部使用MyBits-Plus自带分页,就不需要PageHelper了,自动分页,MyBits-Plu示例1
@DS("salver1")
@Mapper
@Repository
public interface BizLocationMapper extends BaseMapper<BizLocation> {
/**
* 自定义分页
* com.baomidou.mybatisplus.core.metadata.page: 不需要处理,自动分页
* paramVo: 对应使用:#{cm.locationId}取参
*/
IPage<BizLocation> customizedPage(IPage<BizLocation> page,@Param(Constants.COLUMN_MAP) BizLocation paramVo);
}
//lflk、zyt、jhmy中全部使用MyBits-Plus自带分页,就不需要PageHelper了,自动分页,MyBits-Plu示例2
public interface GovLogsService extends IService<GovLogs> {
IPage<GovLogs> customizePage(IPage<GovLogs> page, GovLogs param);
}
@Slf4j
@AllArgsConstructor
@Service
public class GovLogsServiceImpl extends ServiceImpl<GovLogsMapper, GovLogs>
@Override
public IPage<GovLogs> customizePage(IPage<GovLogs> page, GovLogs param) {
return this.page(page, this.getQueryWrapper(param));
}
private LambdaQueryWrapper<GovLogs> getQueryWrapper(GovLogs param) {
LambdaQueryWrapper<GovLogs> query = Wrappers.lambdaQuery();
query.eq(Objects.nonNull(param.getLogId()), GovLogs::getLogId, param.getLogId());
query.eq(Objects.nonNull(param.getType()), GovLogs::getType, param.getType());
query.eq(Objects.nonNull(param.getMethod()), GovLogs::getMethod, param.getMethod());
query.eq(Objects.nonNull(param.getIsSuccess()), GovLogs::getIsSuccess, param.getIsSuccess());
query.eq(Objects.nonNull(param.getResponseCode()), GovLogs::getResponseCode, param.getResponseCode());
query.likeRight(StringUtils.isNotEmpty(param.getUrl()), GovLogs::getUrl, param.getUrl());
query.like(StringUtils.isNotEmpty(param.getRequest()), GovLogs::getRequest, param.getRequest());
query.like(StringUtils.isNotEmpty(param.getResponse()), GovLogs::getResponse, param.getResponse());
query.ge(Objects.nonNull(param.getBeginTime()), GovLogs::getCreateTime, param.getBeginTime());
query.le(Objects.nonNull(param.getEndTime()), GovLogs::getCreateTime, param.getEndTime());
query.orderByDesc(GovLogs::getCreateTime);
return query;
}
}
2、作用原理
在上述代码的第一行代码设置分页参数后,
PageHelper 会把设置的分页参数封装到一个 Page 对象中并存储到一个 ThreadLocal中。
其中涉及到的关键源码有:PageMethod #startPage()、PageMethod #setLocalPage。
最后,让我们对 PageHelper 插件分页的原理做下总结:
- MvBatis 启动阶段、会解析配置文件、并将解析后的结果保存到一个 Configuration 对象中。其中,我们配置的插件,会被解析并保存到 Confiquration 对象的 InterceptorChain 对象中;
- MyBatis 的执行阶段,会先为当前的 executor 对象创建一个 JDK的动态代理对象,其中,动态代理类的关键实现就是调用插件的 intercept()。
- 在插件的 intercept)中,PageHelper 会先从 ThreadLocal 中获取参数的信息,然后在原始 SQL 的尾部拼接上 LMIT 分页语句,从而实现物理分页的效果。
3、数据方言实现
3.1、MySqlDialect
在原始SQL尾部添加分页参数
//com.github.pagehelper.dialect.helper.MySqlDialect
//com.baomidou.mybatisplus.extension.plugins.pagination.dialects.MySqlDialect 也有类似的实现
@Override
public String getPageSql(String sql, Page page, CacheKey pageKey) {
StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
sqlBuilder.append(sql);
if (page.getStartRow() == 0) {
sqlBuilder.append("\n LIMIT ? ");
} else {
sqlBuilder.append("\n LIMIT ?, ? ");
}
return sqlBuilder.toString();
}
3.2、OracleDialect
//com.github.pagehelper.dialect.helper.OracleDialect
//com.baomidou.mybatisplus.extension.plugins.pagination.dialects.Oracle12cDialect mybatisplus类似的方言实现
@Override
public String getPageSql(String sql, Page page, CacheKey pageKey) {
StringBuilder sqlBuilder = new StringBuilder(sql.length() + 120);
sqlBuilder.append("SELECT * FROM ( ");
sqlBuilder.append(" SELECT TMP_PAGE.*, ROWNUM PAGEHELPER_ROW_ID FROM ( \n");
sqlBuilder.append(sql);
sqlBuilder.append("\n ) TMP_PAGE)");
sqlBuilder.append(" WHERE PAGEHELPER_ROW_ID <= ? AND PAGEHELPER_ROW_ID > ?");
return sqlBuilder.toString();
}
3.3、SqlServer2012Dialect
//com.github.pagehelper.dialect.helper.SqlServer2012Dialect
//com.baomidou.mybatisplus.extension.plugins.pagination.dialects.SQLServerDialect mybatisplus中类似的方言实现
@Override
public String getPageSql(String sql, Page page, CacheKey pageKey) {
StringBuilder sqlBuilder = new StringBuilder(sql.length() + 64);
sqlBuilder.append(sql);
sqlBuilder.append("\n OFFSET ? ROWS FETCH NEXT ? ROWS ONLY ");
pageKey.update(page.getPageSize());
return sqlBuilder.toString();
}