Mybatis分页插件PageHelper失效

1,场景

错误:

//因为查询前要先去数据库查询几个条件,就会查询数据库。导致分页参数被(1)号查询消费了,所以(2)查询就没有使用到分页参数
public PageInfo<ArticleInfo> findPage(ArticleInfo entity) {
    PageHelper.startPage(entity.getPageNum(), entity.getPageSize());
    if (entity.getTopicId() != null) {
        List<String> codes = new ArrayList<>();
        (1)BaikeTopic baikeTopic = itBaikeService.get(entity.getTopicId());
        codes.add(baikeTopic.getTopicCode());
        List<String> allCodesById = itBaikeService.getAllCodesById(entity.getTopicId(), codes);
        entity.setTopicCode(StringUtils.join(allCodesById, ","));
    }
        (2)List<ArticleInfo> list = this.findList(entity);
    list.forEach((e) -> {
        e.setStatusName(ArticleEnum.find(e.getStatus()).getName());
        e.setApproveBy(itBaikeService.getCheckUserInfo(e.getTopicCode()));
    });
    return new PageInfo<>(list);
}

正确 :

PageHelper.startPage(entity.getPageNum(), entity.getPageSize());应该放在(2)查询上面

2,原因分析

PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。

3,PageHelper源码分析

@Intercepts({@Signature(
    type = Executor.class,
    method = "query",
    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
), @Signature(
    type = Executor.class,
    method = "query",
    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}
)})
public class PageInterceptor implements Interceptor {
    protected Cache<CacheKey, MappedStatement> msCountMap = null;
    private Dialect dialect;
    private String default_dialect_class = "com.github.pagehelper.PageHelper";
    private Field additionalParametersField;

    public PageInterceptor() {
    }

    public Object intercept(Invocation invocation) throws Throwable {

        try{
         //处理SQL

         String pageSql = this.dialect.getPageSql(ms, boundSql, parameter, rowBounds,     cacheKey);

   }finally {
       //清楚ThreadLocal中存储的分页参数
       this.dialect.afterAll();
  
 public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }
   }


    }
}

public String getPageSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, CacheKey pageKey) {
    String sql = boundSql.getSql();
    //获取分页数据
    Page page = this.getLocalPage();

    //重置查询sql
    return this.getPageSql(sql, page, pageKey);
}

 

 

 

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 ");
        sqlBuilder.append(page.getPageSize());
    } else {
        sqlBuilder.append(" LIMIT ");
        sqlBuilder.append(page.getStartRow());
        sqlBuilder.append(",");
        sqlBuilder.append(page.getPageSize());
        pageKey.update(page.getStartRow());
    }

    pageKey.update(page.getPageSize());
    return sqlBuilder.toString();
}

 PageHelper.startPage(entity.getPageNum(), entity.getPageSize());

 PageHelper继承了PageMethod

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.github.pagehelper.page;

import com.github.pagehelper.ISelect;
import com.github.pagehelper.Page;
import com.github.pagehelper.util.PageObjectUtil;

public abstract class PageMethod {
    protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal();

    public PageMethod() {
    }

    protected static void setLocalPage(Page page) {
        LOCAL_PAGE.set(page);
    }

    public static <T> Page<T> getLocalPage() {
        return (Page)LOCAL_PAGE.get();
    }

    public static void clearPage() {
        LOCAL_PAGE.remove();
    }

    public static long count(ISelect select) {
        Page<?> page = startPage(1, -1, true);
        select.doSelect();
        return page.getTotal();
    }

    public static <E> Page<E> startPage(int pageNum, int pageSize) {
        return startPage(pageNum, pageSize, true);
    }

    public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count) {
        Page<E> page = new Page(pageNum, pageSize, count);
        setLocalPage(page);
        return page;
    }

    public static <E> Page<E> offsetPage(int offset, int limit) {
        return offsetPage(offset, limit, true);
    }

    public static <E> Page<E> offsetPage(int offset, int limit, boolean count) {
        Page<E> page = new Page(new int[]{offset, limit}, count);
        setLocalPage(page);
        return page;
    }
    
    public static <E> Page<E> startPage(Object params) {
        Page<E> page = PageObjectUtil.getPageFromObject(params, true);
        setLocalPage(page);
        return page;
    }
}

4,mybatis插件原理

Mybatis插件原理及案例_身体好饿的博客-CSDN博客

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值