分析Mybatis的分页插件PageHelper的源码

本次我们分析PageHelper的源码,查看它的执行过程;

1、PageHelper的版本

<dependency>
                <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>3.7.5</version>
        </dependency>

2、首先我们先看在代码中怎么使用的

PageHelper.startPage(1,2);
List<User> users = sqlSession.selectList("UserMapper.queryAllUser");
users.forEach(u -> System.out.println(u));

3、分析PageHelper.startPage(1,2),这个是在设置当前页和每页查询的数据量

PageHelper里面有一个静态方法:
public static Page startPage(int pageNum, int pageSize) {
        return startPage(pageNum, pageSize, true);
    }
最后调用的方法:
    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);
        SqlUtil.setLocalPage(page);
        return page;
    }
其实就是创建了一个Page对象,设置一些参数,然后把Page对象放入了ThreadLocal对象里面。
创建对象的时候还计算了开始和结束的行
private Page(int pageNum, int pageSize, int total, Boolean reasonable) {
        super(0);
        if (pageNum == 1 && pageSize == Integer.MAX_VALUE) {
            pageSizeZero = true;
            pageSize = 0;
        }
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.total = total;
        calculateStartAndEndRow();// 计算起止行号
        setReasonable(reasonable);
    }
private void calculateStartAndEndRow() {
        this.startRow = this.pageNum > 0 ? (this.pageNum - 1) * this.pageSize : 0;
        this.endRow = this.startRow + this.pageSize * (this.pageNum > 0 ? 1 : 0);
    }
// 将创建的page对象放入了ThreadLocal对象中
SqlUtil.setLocalPage(page); 
public static void setLocalPage(Page page) {
        LOCAL_PAGE.set(page);
    }
private static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();

4、PageHelper实现Interceptor接口,在接口上面有一个注解:

@Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}));意思也就是说拦截了Executor的query方法,方法的参数是:MappedStatement,Object,RowBounds,ResultHandler。

实现Interceptor接口会重写3个方法:

/**
     * Mybatis拦截器方法
     *
     * @param invocation 拦截器入参
     * @return 返回执行结果
     * @throws Throwable 抛出异常
     */
    public Object intercept(Invocation invocation) throws Throwable {
        return sqlUtil.processPage(invocation);
    }

    /**
     * 只拦截Executor
     *
     * @param target
     * @return
     */
    public Object plugin(Object target) {
        if (target instanceof Executor) {
            return Plugin.wrap(target, this);
        } else {
            return target;
        }
    }

    /**
     * 设置属性值
     *
     * @param p 属性值
     */
    public void setProperties(Properties p) {
        //MyBatis3.2.0版本校验
        try {
            Class.forName("org.apache.ibatis.scripting.xmltags.SqlNode");//SqlNode是3.2.0之后新增的类
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("您使用的MyBatis版本太低,MyBatis分页插件PageHelper支持MyBatis3.2.0及以上版本!");
        }
        //数据库方言
        String dialect = p.getPro
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值