Java架构直通车——结合源码理解PageHelper

2023-10-30

PageHelper实现方式?

  1. PageHelper首先将前端传递的参数保存到page这个对象中,接着将page的副本存放入ThreadLoacl中,这样可以保证分页的时候,参数互不影响。
  2. 接着利用了mybatis提供的拦截器,取得ThreadLocal的值,重新拼装分页SQL,执行查询的时候通过拦截器在sql语句中添加分页参数,之后实现分页查询。
  3. 最后在finally代码段中自动清除了ThreadLocal存储的对象,防止内存泄漏。

第一步:在ThreadLocal中保存Page

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

	public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
		//page对象存储了如pageNum、pageSize、orderBy等查询条件
        Page<E> page = new Page(pageNum, pageSize, count);
        page.setReasonable(reasonable);
        page.setPageSizeZero(pageSizeZero);
        Page<E> oldPage = getLocalPage();
        if (oldPage != null && oldPage.isOrderByOnly()) {
            page.setOrderBy(oldPage.getOrderBy());
        }

        setLocalPage(page);//存储到ThreadLocal中
        return page;
    }

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

Debug到这个位置,其实Page.startpage已经完成了它应该做的,接下来就是执行selectByPrimaryKey()这个方法了。
在这里插入图片描述

第二步:SqlSessionFactory注入Interceptor

继续Debug下一句selectByPrimaryKey(),我们来到了这个类:

public class MapperProxy<T> implements InvocationHandler, Serializable {
	...
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            return Object.class.equals(method.getDeclaringClass()) ? method.invoke(this, args) : this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession);
        } catch (Throwable var5) {
            throw ExceptionUtil.unwrapThrowable(var5);
        }
    }
}

先不管来到的哪个方法,光是看InvocationHandler就能明白,这是个动态代理、。

在这个类里,Mybatis完成了初始化的过程:
在这里插入图片描述
初始化的的核心流程就是 读取配置文件 到 Congiguration实例,之后生成全局公用的 SqlSessionTemplate 以SqlSessionFactory实例。

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
	...
	private Interceptor[] plugins;

	protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
		...
		if (!ObjectUtils.isEmpty(this.plugins)) {
            Stream.of(this.plugins).forEach((plugin) -> {
                targetConfiguration.addInterceptor(plugin);
                LOGGER.debug(() -> {
                    return "Registered plugin: '" + plugin + "'";
                });
            });
        }
		...
	}
}

在SqlSessionFactoryBean中,我们注意到,其属性包含了Interceptor数组,而buildSqlSessionFactory()方法通过在Configuration加入plugins,完成Interceptor的注入。

初始化完成后,接下来是Mapper的查询流程,是一个调用链,如下:
在这里插入图片描述
核心是 configuration.newExecutor()方法,会加载拦截链,也就是pageInterceptor。

第三步:PageInterceptor实现分页

PageHelper最核心的逻辑在 PageInterceptor 中,PageInterceptor 是一个拦截器。

public class PageInterceptor implements Interceptor {
	private volatile Dialect dialect;
    private String countSuffix = "_COUNT";
    protected Cache<String, MappedStatement> msCountMap = null;
    private String default_dialect_class = "com.github.pagehelper.PageHelper";
    ...
}

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java架构直通车——结合源码理解PageHelper 的相关文章

  • 搜索引擎的故事

    本篇要介绍的搜索引擎包括 Shodan censys 钟馗之眼 Google FoFa Dnsdb等 介绍的内容主要是这几款搜索引擎的一些高级语法 掌握高级语法会让搜索结果更准确 Google搜索引擎 这里之所以要介绍google搜索引擎
  • 日常开发中常用的JVM调优参数有哪些呢?

    下文笔者讲述JVM调优参数的简介说明 如下所示 Xms2g 初始化推大小为 2g Xmx2g 堆最大内存为 2g XX NewRatio 4 设置年轻的和老年代的内存比例为 1 4 XX SurvivorRatio 8 设置新生代 Eden

随机推荐

  • python找不到对象报错代码,python2.7源码安装方式

    安装python2 7 下载Python 2 7 下载地址 解压安装 tar xzvf Python 2 7 15 tgz cd Python 2 7 15 configure prefix opt local python enable
  • Ubuntu下安装MySQL 以及C++连接MySQL

    一 简单分享Ubuntu 16 04下安装MySQL的过程 首先执行下面三条命令 sudo apt get install mysql server 此步骤可以省略 已经启用docker mysql服务容器 sudo apt get isn
  • ctf.show刷题记录_web(1-10)

    ctf平台 ctfshow https ctf show 1 签到 解题 base64解码 ctfshow 0da357d0 359b 47e1 80dc 5c02212725e5 2 web2 解题 正常页面 输入用户名admin 密码a
  • koin框架预研文档

    背景 koin框架简介 Koin框架 适用于使用Kotlin开发 是一款轻量级的依赖注入框架 无代理 无代码生成 无反射 相对于dagger 而言更加适合Kotlin语 引入目的 目前app比较常用的是dagger框架 dagger框架属于
  • echarts显示纵坐标轴上的箭头

    问题描述 提示 这里描述具体问题 在使用echarts时默认纵坐标是不显示的 所以你在怎么设置样式也不会显示出来 需要手动在代码里面写出来 yAxis name type value axisLine show true 这个是需要主动添加
  • java实现插入排序+代码推导

    图解 代码推导 package data structure import java util Arrays public class insertSort public static void main String args int a
  • 使用Eclipse IDE for GNU ARM搭建STM32的开发环境

    01 下载必要的文件 1 1 安装java运行环境 这一步比较简单 就不细说了 1 2 需要下载四个文件gnumcueclipse gcc arm none eabi xpack windows build tools jlink gnum
  • VS2017无法登录:我们无法刷新此账户的凭证、我们无法添加此账户发送请求时出错、评估期已结束,请登录以解除产品锁定

    之前下了vs但是开的有点慢习惯用codeblocks了 之后因为vs有快速生成类getset函数的快捷键就跑回来用 这个时候vs提示我 评估期已结束 请登录以解除产品锁定 问题描述 vs2017许可证到期 如何评估 解决方法 登录更新许可证
  • IRI-2016 Matlab 使用教程

    IRI2016在线计算模型 https ccmc gsfc nasa gov modelweb models iri2016 vitmo php 同时IRI2016还有Matlab和Fortran版本 其中的Matlab也是通过在线的接口进
  • 直流电机PID调节——P

    其实要用PID调节的话 最好是使用带有编码器的比较高端一点的直流减速电机 但是因为它价格有点贵 所以我们一般做智能小车就会选用普通的直流电机 但是普通的直流电机也是可以使用PID调节的 虽然它的效果没有带编码器得到直流减速电机的好 但是我们
  • 单片机检测脉冲个数c语言程序,C51单片机脉冲累加器(C语言程序)

    void timer0 void interrupt 1 using 1 switch count case 1 TH0 2700 pwm value 256 TL0 2700 pwm value 256 while 1 if pwm va
  • 分享个最佳的代码片段在线测试网站

    Its our pleasure to share best resources tools for web developers and designer Today we are 1 非常好的在线编译调试网站 https www onl
  • 10.网络爬虫—MongoDB详讲与实战

    网络爬虫 MongoDB详讲与实战 MongoDB MongoDB安装 创建数据目录 1 数据库操作 2 集合操作 3 文档操作 4 索引操作 5 聚合操作 6 备份与恢复 MongoDB增删改查 mongodb集合的增删改查 数据插入到表
  • 知识点记录-abase是什么

    Abase Abase是一套支持redis协议的分布式KV存储系统 是字节跳动自研的一套数据库系统 对在线业务发挥着核心作用 支持redis协议 高可用 低延迟 高扩展的kv存储 常用于redis的大容量持久化场景 为什么采用Abase r
  • 在react项目中调用百度地图API的BMap后报错解决方案

    我这里是使用了react typescript技术栈 在 public index html文件中引入百度地图项目的文件 就相当于是全局导入了 但是并不能直接使用相关的API 需要在使用的文件中这样声明一下 然后就可以直接使用了 const
  • stm32专题二十九:Flash 读写保护

    设置Flash的读写保护 其实就是操作内部Flash的选项字节 选项字节在内部Flash的主存储页之后 由于是Flash 不能像内存RAM一样随意写入 由于Flash的写入特性 只能将 1 写成 0 而如果要确保写入数据的绝对正确 则需要先
  • pytorch:nn.ReLU(inplace=True) 中的参数 inplane 的作用

    pytorch 的激活函数nn Relu 有一个参数 inplace 其作用是 该nn Relu 函数计算得到的输出是否更新传入的输出 正常情况下 一个卷积操作 首先经过卷积层 接着是正则化 Normalize 最后经过激活函数 而输入激活
  • Excel多行转置为一列

    原始数据如下 想把上述数据变成下边这个样子 面板模型数据录入需要用到下边这个形式的数据 步骤 1 先把所有原始数据转置 2 再在153 19下的单元格输入 C2 输入完之后 16 85就会在153 19下的单元格处了 再先横向 后纵向下拉即
  • 解决IDEA安装Python插件,下载失败的方法

    一 问题 通过file gt settings gt Plugins 安装python时 会提示下载失败 可以采用以下方法解决 二 解决办法 1 在help about中查看IDEA版本 作者的是181 4445 2 在https plug
  • Java架构直通车——结合源码理解PageHelper

    PageHelper实现方式 PageHelper首先将前端传递的参数保存到page这个对象中 接着将page的副本存放入ThreadLoacl中 这样可以保证分页的时候 参数互不影响 接着利用了mybatis提供的拦截器 取得Thread