Mybatis-PageHelper源码读后感

一、整体感受

PageHelper源码整体简洁,实现巧妙,是精进自己代码功力的必读佳作。加之前段时间正好在阅读dynamic-tp源码中看到plugin模式的实现,虽然在我看的dynamic-tp源码版本中并未在其他地方使用,但是其类的结构实现和单测让我整体学习了该模式的妙用,加上结合xfg的small-mybatis源码中plugin模式的实现,发现两者几乎一摸一样。这些积累让我能够更好的理解PageHelper的源码,仿佛冥冥之中指引着我,还是说,世间万物皆有异曲同工之妙,哈哈哈。
在这里插入图片描述
在这里插入图片描述

二、基于Mybatis Pugin实现行为注入

Mybatis Plugin 的插件功能是非常重要的一个功能点,包括我们可以结合插件的扩展;分页、数据库表路由、监控日志等。而这些核心功能的扩展,都是来自于 Mybatis Plugin 提供对类的代理扩展,并在代理中调用我们自定义插件的逻辑行为。

PageHelper正是借助Mybatis Pulgin的插件实现了分页功能的扩展,能够巧妙的通过简单上下文配置ThreadLocal,是的,你没看错,ThreadLocal就实现分页参数的整个session中的传递。实现分页参数的注入,拦截SQL,在通过Interceptor实现整体分页结构中的count和limit操作。

protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();
if (!dialect.skip(ms, parameter, rowBounds)) {
                //判断是否需要进行 count 查询
                if (dialect.beforeCount(ms, parameter, rowBounds)) {
                    //查询总数
                    Long count = count(executor, ms, parameter, rowBounds, resultHandler, boundSql);
                    //处理查询总数,返回 true 时继续分页查询,false 时直接返回
                    if (!dialect.afterCount(count, parameter, rowBounds)) {
                        //当查询总数为 0 时,直接返回空的结果
                        return dialect.afterPage(new ArrayList(), parameter, rowBounds);
                    }
                }
                resultList = ExecutorUtil.pageQuery(dialect, executor,
                        ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);
            } else {
                //rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页
                resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
            }

三、Page 强转妙用

@Test
public void testPageHelper(){

      PageHelper.startPage(1, 10);
      List<DBAccountHandlerRule> result = accountHandlerRuleMapper.selectAll();
      PageInfo<DBAccountHandlerRule> pageInfo = new PageInfo<>(result);

      System.out.println(pageInfo);
  }

看到这里不禁思考,为何mapper执行SQL的result能用PageInfo类直接承接?翻看源码发现mapper查询的list对象就是Page对象,巧妙使用了任意子类对象可强转位父类对象的特性。

public class Page<E> extends ArrayList<E> implements Closeable {
    private static final long serialVersionUID = 1L;

    /**
     * 页码,从1开始
     */
    private int pageNum;
    /**
     * 页面大小
     */
    private int pageSize;
    .....
}

PageInfo中


    /**
     * 包装Page对象
     *
     * @param list
     */
    public PageInfo(List<T> list) {
        this(list, 8);
    }

四、设计思想本地方言Dialect

在涉及到插件功能开发的大部分应用中,都离不开适配层的开发,PageHelper底层数据库SQL的兼容,显得尤为重要,Dialect的设计思想正好匹配不同数据库关于SQL的兼容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值