MyBatis 分页插件 PageHelper-Dazer007

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。

PageMethod
PageInterceptor
最后,让我们对 PageHelper 插件分页的原理做下总结:

  1. MvBatis 启动阶段、会解析配置文件、并将解析后的结果保存到一个 Configuration 对象中。其中,我们配置的插件,会被解析并保存到 Confiquration 对象的 InterceptorChain 对象中;
  2. MyBatis 的执行阶段,会先为当前的 executor 对象创建一个 JDK的动态代理对象,其中,动态代理类的关键实现就是调用插件的 intercept()。
  3. 在插件的 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();
    }

3、数据方言实现

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dazer007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值