温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Mybatis第三方PageHelper分页插件怎么用

发布时间:2022-02-23 14:09:04 来源:亿速云 阅读:267 作者:小新 栏目:开发技术

这篇文章将为大家详细讲解有关Mybatis第三方PageHelper分页插件怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

    用法

    Mybatis第三方PageHelper分页插件怎么用Mybatis第三方PageHelper分页插件怎么用

    此时commentAnalyses为Page对象(PageHelper插件包内定义的)

    Mybatis第三方PageHelper分页插件怎么用

    而Page对象继承自JDK中的ArrayList,扩展并封装了一些page相关的字段,如页码,每页大小,总记录数,总页数等。

    Mybatis第三方PageHelper分页插件怎么用

    Mybatis第三方PageHelper分页插件怎么用原理

    我们就加了一行,它是如何帮助我们实现分页的呢?请往下看。

    PageHelper.startPage做了什么

    我们看这一行PageHelper.startPage(pageIndex, pageSize);做了什么。这个类中重载了好多个startPage方法,最终调用到如下的一个方法

    Mybatis第三方PageHelper分页插件怎么用

    Mybatis第三方PageHelper分页插件怎么用可以看到该方法将分页信息作为构造器参数实例化Page对象,调用SqlUtil.getLocalPage()获取一个旧的Page对象,最后调用SqlUtil.setLocalPage(page);把新创建的Page对象set进去。

    我们看看这两个方法做了什么。如下,很简单,从ThreadLocal中获取Page对象,将Page对象set到ThreadLocal中。知道ThreadLocal作用的不用多说,不知道的可以理解为用于保存本地变量,并与线程绑定。

    Mybatis第三方PageHelper分页插件怎么用

    Mybatis第三方PageHelper分页插件怎么用看到这我们暂且将这一行的作用记为,创建并保存Page对象(分页信息)到ThreadLocal中。

    Page分页信息在哪使用

    那么既然保存了,就有使用的地方。

    我通过代码追踪的方式定位到被调用的地方,通过回溯,发现是从这个类com.github.pagehelper.dialect.AbstractDialect发起调用的

    Mybatis第三方PageHelper分页插件怎么用

    点进去看了一下,主要是取出Page对象用于做一些判断,或保存page相关的信息。应该后续会涉及到

    Mybatis第三方PageHelper分页插件怎么用

    拦截器

    上述AbstractDialect类中的这些方法再回溯,指向了

    com.github.pagehelper.util.SqlUtil#doIntercept方法,intercep调用了doIntercep方法,

    Mybatis第三方PageHelper分页插件怎么用

    继续往上追踪来到了com.github.pagehelper.PageHelper#intercept,这是Interceptor接口的方法。

    Mybatis第三方PageHelper分页插件怎么用

    然后是org.apache.ibatis.plugin.Plugin#invoke调用了com.github.pagehelper.PageHelper#intercept

    可以看到PageHelper实现了Interceptor,这个接口是Mybatis官方提供的,中文意思是拦截器,所以有可能是通过实现这个拦截器做了某些操作来实现分页的。

    插件

    通过代码追踪我们看到Interceptor的intercept方法是在Mybatis的一个org.apache.ibatis.plugin.Plugin类的invoke方法中调用的,而这个Plugin类实现了JDK的java.lang.reflect.InvocationHandler接口,这是JDK代理接口。

    Mybatis第三方PageHelper分页插件怎么用

    这个Plugin中有一个wrap方法会返回一个代理类,所以当调用这个代理类的方法时就会走到上面的invoke方法,就可能会进到拦截器的intercept方法。

    Mybatis第三方PageHelper分页插件怎么用

    所以我们看这个warp在哪调的,就知道啥时候创建这个代理类。就是在上面的PageHelper中,再贴一下代码

    Mybatis第三方PageHelper分页插件怎么用

    拦截器链

    而这个PageHelper中的plugin方法是实现自Interceptor拦截器接口,所以会有一个地方统一调这个方法,往上追溯就会发现是在org.apache.ibatis.plugin.InterceptorChain拦截器链中调用的,如下。

    Mybatis第三方PageHelper分页插件怎么用

    该类有一个List保存所有拦截器,还有三个方法,分别是pluginAll用于调用所有拦截器的plugin方法,addInterceptor添加拦截器,getInterceptors获取拦截器链。

    看到这大致明白了它的原理,PageHelper通过实现Mybatis的Interceptor接口实现分页,Mybatis通过InterceptorChain调用所有Interceptor。

    加载&调用拦截器

    那么我们看看Mybatis的拦截器是什么时候添加到拦截器链,什么时候被调用的。

    通过代码追溯,发现在Configuration的addInterceptor方法中调用添加方法,Configuration.addInterceptor是在XMLConfigBuilder的pluginElement方法中被调用

    Mybatis第三方PageHelper分页插件怎么用

    Mybatis第三方PageHelper分页插件怎么用而XMLConfigBuilder是解析XML方式的Mybatis的配置的,顾名思义pluginElement方法是解析XML中plugin相关的配置节点的

    Mybatis第三方PageHelper分页插件怎么用

    而我们确实在XML中配置了plugin

    Mybatis第三方PageHelper分页插件怎么用

    所以我们现在知道了mybatis的拦截器是在Mybatis解析配置文件时,解析plugins节点时添加到InterceptorChain中的。

    拦截器什么时候调用的。我们看InterceptorChain的pluginAll方法在哪调的,通过代码追踪有如下四个地方调用拦截器链

    Mybatis第三方PageHelper分页插件怎么用

    @Intercepts注解

    而PageHelper这个拦截器,我们可以发现这个类上有一个@Intercepts注解,这个注解接收的值为@Signature注解,在Signature注解配置了,Executor.class,query还有四个class:MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class。

    Mybatis第三方PageHelper分页插件怎么用

    了解Mybatis的插件机制的就明白了,这一行配置的意思是拦截Executor中的query方法,方法参数列表类型是MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class,就是下面这个方法。

    Mybatis第三方PageHelper分页插件怎么用

    所以看到这,我们可以断定InterceptorChain的pluginAll方法在上述调用点的第四个,也就是org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType),可想而知newExecutor,也就是创建Executor实例,可以断定,创建Executor时通过PageHelper的plugin方法包装了Executor,返回的是Executor的代理类。下面会讲到创建动态代理。

    Mybatis第三方PageHelper分页插件怎么用

    Mybatis第三方PageHelper分页插件怎么用通过PageHelper创建代理对象

    我们在正向回顾一下,如何调到PageHelper的。首先进入到pluginAll

    Mybatis第三方PageHelper分页插件怎么用

    然后会调到PageHelper的plugin方法,内部又调Plugin的warp方法

    Mybatis第三方PageHelper分页插件怎么用

    我们看看Plugin.wrap方法干了啥,代码如下。代码跟过来我们知道现在的target是Executor,interceptor是PageHelper。首先获取PageHelper拦截信息,然后筛选target是否是需要拦截的类型,这里会进入if判断逻辑,返回Executor的代理对象。

    Mybatis第三方PageHelper分页插件怎么用

    所以这时创建的Executor实例是代理对象,那么就会在某个时候调用代理的invoke方法(org.apache.ibatis.plugin.Plugin#invoke),invoke调Interceptor拦截器的intercept方法,从而调PageHelper的intercept方法执行分页逻辑

    org.apache.ibatis.plugin.Plugin#invoke ==》 com.github.pagehelper.PageHelper#intercept

    拦截器的调用源头-动态代理

    因为返回的是Executor的动态代理,所以肯定是调用Executor的某个方法时触发进到invoke方法,具体在哪调的不好找。我们通过打断点的方式看是从哪进invoke方法的,首先断点打到Plugin的invoke方法内

    Mybatis第三方PageHelper分页插件怎么用

    通过调用栈看到是org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)调过来的,在invoke方法内判断了目标方法是不是我们要拦截的方法,因为PageHelper上注解的也是拦截这个方法,所以会进入到Plugin的invoke方法的第61行。所以就会进入到PageHelper的intercept方法,执行具体的拦截逻辑。

    分页逻辑

    思路就是拼SQL。

    通过代码跟踪,最终的分页逻辑是在com.github.pagehelper.util.SqlUtil#doIntercept方法中,第162行,获取分页SQL,

    调用

    com.github.pagehelper.dialect.AbstractDialect#getPageSql(org.apache.ibatis.mapping.MappedStatement, org.apache.ibatis.mapping.BoundSql, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.cache.CacheKey)

    Mybatis第三方PageHelper分页插件怎么用

    com.github.pagehelper.dialect.AbstractDialect#getPageSql(org.apache.ibatis.mapping.MappedStatement, org.apache.ibatis.mapping.BoundSql, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.cache.CacheKey)中调用com.github.pagehelper.dialect.AbstractDialect#getPageSql(java.lang.String, com.github.pagehelper.Page, org.apache.ibatis.session.RowBounds,org.apache.ibatis.cache.CacheKey),是一个抽象方法,具体实现有好多种

    Mybatis第三方PageHelper分页插件怎么用

    我们看mysql的,在原始SQL 拼接了" limit ?,?"

    Mybatis第三方PageHelper分页插件怎么用

    关于“Mybatis第三方PageHelper分页插件怎么用”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI