过往精彩文章:
Mybatis源代码分析的SqlSessionFactory
Mybatis源代码分析的任务和执行程序
Mybatis源代码分析的映射器SQL执行过程
Mybatis源代码分析中缓存一级缓存的原理
Mybatis源代码分析中缓存二级缓存的原理
将米巴蒂斯与redis联合对抗L2秘藏
今天给大家分享一个PageHelper,mybatis的分页插件。在解释PageHelper之前,我们需要了解mybatis的插件原理。页面助手
官方网站:https://github.com/pagehelper/Mybatis-PageHelper
一、插件接口
Mybatis定义了一个插件接口org。阿帕奇。伊巴蒂斯。插件。拦截器。任何自定义插件都需要实现这个接口,PageHelper实现了接口的改变
package org . Apache . ibatis . plugin;
导入Java . util . properties;
/**
* @作者克林顿Begin
*/
公共接口拦截器{
对象拦截抛出可抛出;
对象插件;
无效设置属性;
}
1:拦截拦截器,会直接覆盖你拦截对象的真实方法。
2.这是一个生成动态代理对象的方法
3:设置属性它允许您在使用插件时设置参数值。
看com。github。pagehelper。pagehelper的分页实现
/**
* Mybatis拦截器方法
*
* @param调用拦截器输入
* @return返回执行结果
* @ Throwable抛出异常
*/
公共对象拦截引发可投掷{
if {
SqlUtil sqlUtil = getSqlUtil;
返回sqlUtil.processPage;
if{
initSqlUtil;
}
返回sqlUtil.processPage;
}
}
这个方法获取分页核心代码并重构BoundSql对象,这将在下面详细分析
/**
*仅阻止执行者
*
* @param目标
* @返回
*/
公共对象插件{
Executor的目标实例){
return Plugin.wrap;
返回目标;
}
}
这个方法是截取执行器
/**
*设置属性值
*
* @param p属性值
*/
public void set Properties{
checkVersion
//如果有多个数据源,获取jdbcurl后是否关闭数据源
string CloseConn = p . GetProperty;
//求解#97
if){
this . closeConn = boolean . parse boolean;
}
//初始化SqL的PARAMS
SqL . SetParAms;
//数据库方言
字符串方言= p.getProperty;
string RuntimeVaLue = p . GetProperty;
if)& amp;& amp运行时方言. equalsignorecase{
this . AutoRuntimediaSelect = true;
this.autoDialect = false
this . properties = p;
} else if ){
自动学习=真;
this . properties = p;
自动学习=假;
sqlUtil =新sqlUtil;
SqL . SetPropertieS;
}
}
基本属性设置
二、插件初始化
初始化和所有mybatis初始化一样。在上一篇文章中,已经分析了Mybatis源代码分析的SqlSessionFactory
私有void pluginElement引发异常{
if {
for {
string interceptor = child . GetStringAttribute;
properties properties = child . getchildrenaspproperties;
拦截器拦截器=解析器类。newInstance
interceptionrinsitivity . set properties;
configuration.a ddInterceptor;
}
}
}
这里说的是多个实例化的插件对象放入配置,addInterceptor最后存储在一个列表中,以为这样可以同时存储多个插件
第三,外挂拦截
该插件可以拦截mybatis的四个主要对象:ParameterHandler、ResultSetHandler、StatementHandler和Executor。源代码如下
您可以在配置类中找到它
PageHelper使用Executor进行拦截,这在上面的源代码中已经可以看到。
让我看看上图中的newExecutor方法
Executor =interceptor chain . pluginal;
这是为了生成一个代理对象,并在生成代理对象时运行调用方法
四.插件操作
Mybatis自带Plugin方法,源代码如下
公共类插件实现InvocationHandler {
私有对象目标;
私人截击机;
私人地图& lt类别<。?>。,Set & lt方法>。>。signatureMap
私有插件 {
this.target = target
this.interceptor = interceptor
this . signatureMap = signatureMap;
}
公共静态对象包装{
地图<。类别<。?>。,Set & lt方法>。>。signatureMap = getSignatureMap;
类别<。?>。type = target.getClass
类别<。?>。interfaces = getAllInterfaces;
if {
return Proxy.newProxyInstance;
}
返回目标;
}
公共对象调用引发可投掷{
Set<。方法>。methods = signaturemap . get;
if ) {
return interceptor . intercept);
}
return method.invoke;
throw ExceptionTil . Unwrapthrowable;
}
}
私有静态地图& lt类别<。?>。,Set & lt方法>。>。getSignatureMap{
intercepts intercepts sannotation = interceptor . GetClass . GetAnnotation;
//第251期
if {
抛出新的PluginException;
}
sigs = interceptSannotation . value;
地图<。类别<。?>。,Set & lt方法>。>。signatureMap = new HashMap & lt类别<。?>。,Set & lt方法>。>。;
for {
Set<。方法>。methods = SignatureMap . get;
if {
methods = new HashSet & lt方法>。;
signatureMap.put;
}
尝试{
method method = SIG . type . GetMethod;
methods . a DD;
} catch{
抛出新的插件异常;
}
}
返回签名映射;
}
私有静态类& lt?>。getAllInterfaces {
Set<。类别<。?>。>。interfaces = new HashSet & lt类别<。?>。>。;
while {
for {
if){
interfaces . a DD;
}
}
type = type.getSuperclass
}
返回接口到数组;
}
}
wrap方法是生成一个动态代理类。
Invoke方法是一种代理绑定方法,它首先确定签名类和方法是否存在,如果不存在,则直接反映分派被拦截对象的方法;如果它们存在,调度插件的拦截器方法,然后初始化一个调用对象
让我们具体看看PageHelper。当它被执行调用时,程序将跳转到页面帮助器
公共对象拦截引发可投掷{
if {
SqlUtil sqlUtil = getSqlUtil;
返回sqlUtil.processPage;
if{
initSqlUtil;
}
返回sqlUtil.processPage;
}
}
我们正在研究sqlUtil.processPage方法
/**
* Mybatis拦截器方法,这个步骤是嵌套的,以便在异常发生时清除空Threadlocal。
*
* @param调用拦截器输入
* @return返回执行结果
* @ Throwable抛出异常
*/
公共对象进程页抛出可抛出的{
对象结果= _processPage;
返回结果;
clearLocalPage
}
}
继续跟进
/**
* Mybatis拦截器方法
*
* @param调用拦截器输入
* @return返回执行结果
* @ Throwable抛出异常
*/
私有对象_进程页面抛出可抛出的{
Object final args = invoke . GetArgs;
page page =;
//当支持方法参数时,尝试首先获取Page
if {
page = GetPage;
}
//分页信息
行边界行边界=参数;
//当支持方法参数时,如果page ==,表示没有分页条件,不需要分页查询。
if
//当不支持分页参数时,判断LocalPage和RowBounds,判断是否需要分页。
|| {
返回调用。继续;
//不支持分页参数时,page==,这里需要获取
if {
page = GetPage;
}
返回doProcessPage;
}
}
这些只是打包页面的方法,真正的核心是doProcessPage
/**
* Mybatis拦截器方法
*
* @param调用拦截器输入
* @return返回执行结果
* @ Throwable抛出异常
*/
私有页面进程页面抛出可抛出{
//保存行边界状态
行边界行边界=参数;
//获取原ms
Mapped statement ms =参数;
//确定并作为页面资源进行处理
if) {
processMappedStatement
}
//设置当前解析器,每次使用前都会设置,ThreadLocal的值不会有不良影响
ms.getSqlSource)。setParser;
//忽略row bounds——否则会在Mybatis中进行内存分页
args = RowBounds。DEFAULT
//如果只做排序或页面大小零判断,
if ) {
返回doQueryOnly;
}
//简单的根据total的值来判断是否查询count
if {
page.setCountSignal;
//替换MS
args= MsCountMap . get;
//查询总数
Object result = .继续;
//还原Ms。
args= ms;
//设置总数
page.setTotal结果)。get);
if {
返回页面;
}
page . SetTotal;
}
//pageSize >0,页面大小
if
|| rowBounds!= RowBounds。DEFAULT){
//用新的qs替换参数中的MappedStatement
page . setcountssignal;
BoundSql BoundSql = ms . GetBoundSql;
args= parser . SetPageParameter;
page.setCountSignal;
//执行分页查询
Object result = .继续;
//获取处理结果
page.a ddAll结果);
}
ms.getSqlSource)。removeParser
}
//返回结果
返回页面;
}
有两个对象结果=调用。继续上面的执行,第一个是执行统计的总数,第二个是执行分页查询的数据
里面用的是特工。最后,第一次返回总页数,第二次获取分页数据。
V.页面助手的使用
上面解释了Mybatis的插件原理和PageHelper的内部实现,下面具体描述了PageHelper的使用
1.首先增加对maven的依赖:
& lt依赖性>。
& ltgroupId>。com . github . page helper & lt;/groupId>。
& ltartifactId>。pagehelper<。/artifactId >
& lt版本>。4.1.6<。/version>。
& lt/依赖性
2.将以下配置添加到configuration.xml文件中
& lt插件>。
& lt!-页面帮助4 . 1 . 6->;
& ltplugin interceptor = " com . github . page helper . PageHelper " >;
& ltproperty name= "方言" value="mysql"/>
& ltproperty name = " offsetapagenum " value = " false "/>
& ltproperty name = " RowBoundsWithCount " value = " false "/>
& ltproperty name = " page SiZe zero " value = " true "/>
& ltproperty name= "合理" value="false"/>。
& ltproperty name = " SupportMethodArguments " value = " false "/& gt;
& ltproperty name = " returnPageInfo " value = " none "/& gt;
& lt/plugin>。
& lt/plugins>。
相关的字段描述可以在SqlUtilConfig源代码中找到
当订单不能出现故障时,请注意配置,否则将报告错误
原因:org . Apache . ibatis . builder . Builderexception:创建文档实例时出错。原因:org . XML . sax . SaxParseException;行号:57;列号:17;元素类型为“配置”的内容必须匹配"。
at org . Apache . ibatis . parsing . XPath parser . create document
at org . Apache . ibatis . parsing . XPath parser . & lt;init>。
at org . Apache . ibatis . builder . XML . XMLConfigbuilder . & lt;init>。
at . org . Apache . ibatis . session . SqlsessionfactoryBuilder . build
...2个以上
这意味着配置中节点的顺序是属性->:设置->;类型别名->;typenhandlers->;对象工厂->;objectwrappperfactory->;插件->;环境->;databaseidProvider->;映射器插件应该在环境之前和objectWrapperFactory之后,这个顺序不能打乱
3.特定用途
1:分页
SqL session = SessionFactory . OpenSession;
user mapper user mapper = SQL session . GetMapper;
PageHelper.startPage;//第一页每页显示10个项目
页面<。用户>。page = userMapper.findUserAll
2.没有分页
PageHelper.startPage;
3:查询文章总数
PageInfo<。用户>。info =新页面信息<。>。;
1.《pagehelper分页原理 Mybatis插件原理和PageHelper结合实战分页插件(七)》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《pagehelper分页原理 Mybatis插件原理和PageHelper结合实战分页插件(七)》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/keji/1741888.html