MyBatis 分页之拦截器实现

  分页是WEB程序中常见的功能,mybatis分页实现与hibernate不同,相比hibernate,mybatis实现分页更为麻烦。mybatis实现分页需要自己编写(非逻辑分页RowBounds),以mysql为例,使用分页时需要自己在mapper中的sql语句中添加LIMIT #{xx},#{xx}。这种方式不具备可重用性与可拓展性。

  mybatis提供了plugins,plugins实现了拦截器的功能。它可以拦截指定类中的方法,当指定的方法被执行时,mybatis就会自动拦截并完成相应逻辑。通过mybatis的plugins,就可以实现自动分页功能。

  实现分析:拦截查询语句,判断该查询语句是否需要添加分页,修改原来的sql语句,查询得到的总记录数

  具体源码在https://github.com/yuen666/mybatis-pagination

简要思路

  编写Interceptor,拦截StatementHandler中的prapare方法,在mybatis中,执行的是RoutingStatementHandler实现类。该类使用代理的方式来调用BaseStatementHandler。

  

  在每次使用查询语句时,都会调用RoutingStatementHandler.prepare(...),该方法的实现如下:

  

  它调用了delegate的prepare,实现类为BaseStatementHandler,源码如下:

  

  由于每次查询都调用该prepare方法,故可以对RoutingStatementHandler的prepare进行拦截。该方法中拥有connection对象,通过connection对象也可以连接数据库查询总记录数,比较方便。

  关于sql语句的修改。在delegate中,即BaseStatementHandler中,拥有如下几个域:

  

  其中,boundSql中包含了sql语句(boundSql.sql),由于是protected类型,所以可以采用反射的方式获取原sql语句并设置新sql语句。

  总结下:

  1. 拦截StatementHandler的prepare方法
  2. 通过反射获取delegate.boundSql.sql修改并设置
  3. 获取参数connection并查询中记录数

关于反射

  mybaits提供了MetaObject类,该类对反射进行封装。可以通过该类快速的实现获取与设置delegate.boundSql.sql。

private Object getValue(StatementHandler statementHandler, String exp) {
    MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,
            SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
    return metaObject.getValue(exp);
}
private void setValue(StatementHandler statementHandler, String exp, Object obj) {
    MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,
            SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
    metaObject.setValue(exp, obj);
}

  其中的exp为OGNL表达式。

时间: 2024-10-07 06:18:07

MyBatis 分页之拦截器实现的相关文章

Mybatis那些事-拦截器(Plugin+Interceptor)

作者:yhjyumi的专栏 Mybatis的拦截器实现机制,使用的是JDK的InvocationHandler. 当我们调用ParameterHandler,ResultSetHandler,StatementHandler,Executor的对象的时候,实际上使用的是Plugin这个代理类的对象,这个类实现了InvocationHandler接口.接下来我们就知道了,在调用上述被代理类的方法的时候,就会执行Plugin的invoke方法.Plugin在invoke方法中根据@Intercept

MyBatis空where拦截器

最近项目中出现了至少两次因为Mybatis的动态where条件不满足导致实际sql语句的where条件为空,进而查询全表,当数据量比较大的时候,导致OOM的情况. 如何禁止这种情况,个人觉得三种措施: 1.在逻辑层面加充分的参数有效性检查; 2.在where条件中如果索引条件都不满足,加上1=2这种必然失败的条件; 3.Mybatis拦截器; 前两种措施都是依赖人,从这个层面讲,是不靠谱的,即一个策略不是强制的,就是不靠谱的.相对而言,第三种是不依赖程序员的自觉性,是最靠谱的.乘周六有时间,实现

Mybatis Plugin(拦截器)的开发

1.Plugin MyBatis 允许使用插件来拦截的方法调用包括: • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) • ParameterHandler (getParameterObject, setParameters) • ResultSetHandler (handleResultSets, handleOutputParameters) • S

MyBatis 插件之拦截器(Interceptor)

参考 https://blog.csdn.net/weixin_39494923/article/details/91534658 //项目实际使用 package com.yueworldframework.core.mybatis; import com.yueworldframework.core.support.SessionHelper; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mappi

【Mybatis】1、Mybatis拦截器学习资料汇总

MyBatis拦截器原理探究 http://www.cnblogs.com/fangjian0423/p/mybatis-interceptor.html [myBatis]Mybatis中的拦截器 http://blog.csdn.net/moshenglv/article/details/52699976 MyBatis 拦截器 (实现分页功能) http://www.cnblogs.com/jethypc/p/5149183.html 由浅入深分析mybatis通过动态代理实现拦截器(插件

Mybatis之拦截器--获取执行SQL实现多客户端数据同步

最近的一个项目是将J2EE环境打包安装在客户端(使用 nwjs + NSIS 制作安装包)运行, 所有的业务操作在客户端完成, 数据存储在客户端数据库中. 服务器端数据库汇总各客户端的数据进行分析. 其中客户端ORM使用Mybatis. 通过Mybatis拦截器获取所有在执行的SQL语句, 定期同步至服务器. 本文通过在客户端拦截SQL的操作介绍Mybatis拦截器的使用方法. 1. 项目需求 客户分店较多且比较分散, 部分店内网络不稳定, 客户要求每个分店在无网络的情况下也能正常使用系统, 同

Mybatis分页插件

Mybatis分页插件 - PageHelper说明 如果你也在用Mybatis,建议尝试该分页插件,这个一定是最方便使用的分页插件. 该插件目前支持Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库分页. 点击提交BUG 版本说明 最新版本为3.7.5 PageInfo中的judgePageBoudary方法修改: isLastPage = pageNum == pages && pageNum != 1; //改为 isLastPage

分享一个完整的Mybatis分页解决方案

Mybatis 的物理分页是应用中的一个难点,特别是配合检索和排序功能叠加时更是如此. 我在最近的项目中开发了这个通用分页器,过程中参考了站内不少好文章,阅读源码帮助更大minglisoft.cn/technology [背景] 项目框架是 SpringMVC+Mybatis, 需求是想采用自定义的分页标签,同时,要尽量少的影响业务程序开发的.如果你已经使用了JS框架( 如:Ext,EasyUi等)自带的分页机能,是属于前端分页,不在本文讨论范围. [关于问题] 大多数分页器会使用在查询页面,要

MyBatis之拦截器分页

鲁春利的工作笔记,好记性不如烂笔头 数据库的分页主要有物理分页和逻辑分页.    物理分页:数据库本身提供的分页方式,如MySQL的limit.Oracle的rownum.SqlServer的top,好处是效率高,不好的地方就是不同数据库有不同的查询方式.    逻辑分页:从数据库将所有记录查询出来,存储到内存中,然后数据再直接从内存中获取并筛选分页,好处是能够统一查询方式,不好的地方是效率低,因为每次都要把全部数据查询出来再处理. 常用orm框架采用的分页技术:①:hibernate采用的是物