<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          PageHelper實(shí)現(xiàn)分頁原理

          共 4111字,需瀏覽 9分鐘

           ·

          2021-12-11 10:32

          場(chǎng)景

          PageHelper.startPage(page, pageSize);

          看到這句話后開始思考為何它可以直接實(shí)現(xiàn)分頁邏輯,它是怎么實(shí)現(xiàn)的?為何在數(shù)據(jù)庫查詢的前面加上了這句話就可以實(shí)現(xiàn)分頁,里面到底發(fā)生了什么?

          介紹


          com.github.pagehelper.PageHelper是一個(gè)開源的分頁源碼工具


          <dependency>
          <groupId>com.github.pagehelpergroupId>
          <artifactId>pagehelper-spring-boot-starterartifactId>
          <version>1.2.12version>
          dependency>

          配置文件中也需要配置

          # 分頁插件配置
          pagehelper:
          helperDialect: mysql
          supportMethodsArguments: true

          源碼分析

          分頁參數(shù)的傳遞

          public static  Page startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
          Page page = new Page(pageNum, pageSize, count);
          page.setReasonable(reasonable);
          page.setPageSizeZero(pageSizeZero);
          Page oldPage = getLocalPage();
          if (oldPage != null && oldPage.isOrderByOnly()) {
          page.setOrderBy(oldPage.getOrderBy());
          }

          setLocalPage(page);
          return page;
          }

          這段代碼中第一行是寫入?yún)?shù),第二行和第三行都是null,可以不考慮

          主要的代碼是這兩行:

          getLocalPage();
          setLocalPage(page);


          這里用到了一個(gè)ThreadLocal;

          ThreadLocal,很多地方叫做線程本地變量,為變量在每個(gè)線程中都創(chuàng)建了一個(gè)副本,那么每個(gè)線程可以訪問自己內(nèi)部的副本變量。

          展示到這就看不到其他了,這就很尷尬了,然后繼續(xù)看jar包中的代碼,然后發(fā)現(xiàn)了PageInterceptor這個(gè)類,分頁攔截器,前面已經(jīng)設(shè)置了分頁參數(shù)在本地變量中,然后就該是調(diào)用了,很大可能就是在這個(gè)攔截器中進(jìn)行實(shí)現(xiàn)。


          PageInterceptor 實(shí)現(xiàn)Mybatis的Interceptor 接口,進(jìn)行攔截

           public Object intercept(Invocation invocation) throws Throwable {
          try {
          Object[] args = invocation.getArgs();
          MappedStatement ms = (MappedStatement)args[0];
          Object parameter = args[1];
          RowBounds rowBounds = (RowBounds)args[2];
          ResultHandler resultHandler = (ResultHandler)args[3];
          Executor executor = (Executor)invocation.getTarget();
          CacheKey cacheKey;
          BoundSql boundSql;
          if (args.length == 4) {
          boundSql = ms.getBoundSql(parameter);
          cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);
          } else {
          cacheKey = (CacheKey)args[4];
          boundSql = (BoundSql)args[5];
          }

          this.checkDialectExists();
          List resultList;
          if (!this.dialect.skip(ms, parameter, rowBounds)) {
          if (this.dialect.beforeCount(ms, parameter, rowBounds)) {
          Long count = this.count(executor, ms, parameter, rowBounds, resultHandler, boundSql);
          if (!this.dialect.afterCount(count, parameter, rowBounds)) {
          Object var12 = this.dialect.afterPage(new ArrayList(), parameter, rowBounds);
          return var12;
          }
          }

          resultList = ExecutorUtil.pageQuery(this.dialect, executor, ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);
          } else {
          resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
          }

          Object var16 = this.dialect.afterPage(resultList, parameter, rowBounds);
          return var16;
          } finally {
          if (this.dialect != null) {
          this.dialect.afterAll();
          }

          }
          }

          然后進(jìn)入查看ExecutorUtil.pageQuery,看是怎么實(shí)現(xiàn)的:


          查看分頁的sql語句,繼續(xù):

          public String getPageSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, CacheKey pageKey) {
          String sql = boundSql.getSql();
          Page page = this.getLocalPage();
          String orderBy = page.getOrderBy();
          if (StringUtil.isNotEmpty(orderBy)) {
          pageKey.update(orderBy);
          sql = OrderByParser.converToOrderBySql(sql, orderBy);
          }

          return page.isOrderByOnly() ? sql : this.getPageSql(sql, page, pageKey);
          }

          看到最后的三則表達(dá)式后后的getPageSql


          進(jìn)入到MySqlDialect類的getPageSql方法進(jìn)行SQL封裝,根據(jù)page對(duì)象信息增加Limit。分頁的信息就是這么拼裝起來的

          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(" LIMIT ? ");
          } else {
          sqlBuilder.append(" LIMIT ?, ? ");
          }

          return sqlBuilder.toString();
          }

          總結(jié)

          原來PageHelper的分頁功能是在我們執(zhí)行SQL語句之前動(dòng)態(tài)的將SQL語句拼接了分頁的語句,從而實(shí)現(xiàn)了從數(shù)據(jù)庫中分頁獲取的過程。


          瀏覽 135
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  香蕉操逼视频 | 日逼免费观看视频 | 四虎影院日韩无码 | 啪啪网站免费看 | 成年人在线激情电影 |