手写MyBatis分页插件
目录
- 前言
- MyBatis插件
- 手写分页插件
- 总结
前言
在开发查询类的接口时,有一个让开发者比较头疼的问题:分页。
如果每次都要开发者自己去写limit,计算起始行和偏移量就太烦了,于是市面上诞生了一些优秀的分页插件,例如:PageHelper。
PageHelper使用起来非常简单,如下示例代码:
Page page = PageHelper.startPage(1, 10);
//sql: select * from table
mapper.selectList();
调用PageHelper.startPage(1, 10)方法后,在执行SQL时会自动加上limit分页,如下:
select * from table limit 0,10;
查看源码会发现PageHelper.startPage(1, 10)
只做了一件事:构建Page实例存放到本地线程中。
它能修改执行的SQL语句得益于PageInterceptor
类,基于Mybatis提供的Interceptor插件来实现的。
本篇博客并不想分析PageHelper的源码,感兴趣的同学可以自己去研究一下。
MyBatis插件
不管是PageHelper还是其他分页插件,实现的思路都是一样的,给予MyBatis提供的Interceptor插件机制,允许开发者在映射语句执行过程中进行方法的拦截,可以动态修改入参、SQL语句、返回结果等。
MyBatis允许被拦截的方法包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
详情请看官方文档:https://mybatis.org/mybatis-3/zh/configuration.html#plugins
手写分页插件
借鉴PageHelper的思路,自己手写一个分页插件,其实并不难。
Page类存放当前页和大小
//省略getter setter
public class Page {private Integer page;private Integer size;
}
PageUtil通过ThreadLocal传递Page实例
public class PageUtil {// Page通过ThreadLocal传递static final ThreadLocal<Page> THREAD_LOCAL_PAGE = new ThreadLocal<>();public static Page startPage(Integer page, Integer size) {Page pageResult = new Page();pageResult.setPage(page);pageResult.setSize(size);THREAD_LOCAL_PAGE.set(pageResult);return pageResult;}public static Page localPage() {return THREAD_LOCAL_PAGE.get();}public static void remove() {THREAD_LOCAL_PAGE.remove();}
}
PagePlugin,基于Interceptor实现的分页逻辑
// 拦截StatementHandler类的prepare方法
@Intercepts({@Signature(type = StatementHandler.class,method = "prepare",args = {Connection.class, Integer.class})})
public class PagePlugin implements Interceptor {private Properties properties;@Overridepublic Object intercept(Invocation invocation) throws Throwable {Page page = PageUtil.localPage();//没有调用PageUtil.startPage(),则不分页if (page == null) {return invocation.proceed();}//取出原sql,根据page拼接分页sqlRoutingStatementHandler target = (RoutingStatementHandler) invocation.getTarget();BoundSql boundSql = target.getBoundSql();String sql = boundSql.getSql();int limit = (page.getPage() - 1) * page.getSize();ReflectUtil.setFieldValue(boundSql, "sql", sql + " limit " + limit + "," + page.getSize());//删除当前线程的page实例PageUtil.remove();//执行目标方法return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {this.properties = properties;}
}
配置插件
<plugins><plugin interceptor="com.ch.plugins.PagePlugin"></plugin>
</plugins>
Mapper接口
public interface UserMapper {@Select("select * from user")List<User> list();
}
分页测试类
public class PageTest {public static void main(String[] args) throws Exception {String resource = "mybatis.xml";InputStream inputStream = null;try {inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);Configuration configuration = sqlSessionFactory.getConfiguration();SqlSession session = sqlSessionFactory.openSession();UserMapper mapper = session.getMapper(UserMapper.class);// 第1页,每页10条Page page = PageUtil.startPage(1, 10);for (User user : mapper.list()) {System.out.println(user);}session.close();} finally {IoUtil.close(inputStream);}}
}
执行后,控制台输出日志
DEBUG [main] - ==> Preparing: select * from user limit 0,10
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 10
分页成功!
总结
主要记的是思路,分页插件写的比较简陋,只是简单的拼接SQL,也没有考虑到limit分页失效的问题。
感兴趣的同学可以基于这个思路继续优化!!!
手写MyBatis分页插件相关推荐
- Mybatis:Mybatis分页插件
文章目录 1. Mybatis分页插件 1.1 分页插件介绍 1.2 分页插件的使用 1.3 分页插件的参数获取 1.4 分页插件知识小结 分页助手相关 API 1. Mybatis分页插件 1.1 ...
- 使用abel533大神的mybatis分页插件总结
今天使用了abel533大神的mybatis分页插件,遇到了写问题,特意在这里做个总结,方便以后查找. 首先该测试是在本人的ssm基础框架上实现的,有兴趣的可以先看看本人的博客置顶帖.高手就略过吧. ...
- druid连接池初始化慢_从零开始手写 mybatis (三)jdbc pool 从零实现数据库连接池
前景回顾 第一节 从零开始手写 mybatis(一)MVP 版本 中我们实现了一个最基本的可以运行的 mybatis. 第二节 从零开始手写 mybatis(二)mybatis interceptor ...
- (转)淘淘商城系列——MyBatis分页插件(PageHelper)的使用以及商品列表展示
http://blog.csdn.net/yerenyuan_pku/article/details/72774381 上文我们实现了展示后台页面的功能,而本文我们实现的主要功能是展示商品列表,大家要 ...
- 都这么卷了,不懂MyBatis插件开发怎么行,教你实现一个MyBatis分页插件
MyBatis可谓是Java开发工程师必须要掌握的持久层框架,它能够让我们更容易的通过Java代码操作数据库,并且它还有很高的扩展性,我们可以自定义插件,去让MyBatis的功能变的更为强大,本篇文章 ...
- 2. mybatis分页插件使用
1.概述 在做系统的过程中,分页查询是我们经常遇到的一个场景,我们可以借助mybatis分页插件方便的实现分页功能,本文分享怎样使用mybatis分页插件. 2.mybatis分页插件使用 mybat ...
- MyBatis 分页插件
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 1.分页插件使用步骤 2.分页插件的使用 总结 前言 mybatis学习记录 12. MyBatis 分页插件 提示: ...
- 手写mybatis彻底搞懂框架原理
mybatis的前身是iBatis,其源于"Internet"和"abatis"的组合,是一款优秀的持久层框架,它支持定制化SQL.存储过程以及高级映射.myb ...
- springboot整合mybatis分页插件
1.springboot版本为2.0.1,数据库为mysql,引入pagehelper的pom依赖 <!--mybatis分页插件--> <dependency><gro ...
最新文章
- 放大器非线性失真研究装置设计报告_我校信息学院学子再次斩获大学生电子设计竞赛大奖...
- boost::serialization模块实现快速二进制归档的测试程序
- vue中mode的设置
- java显示目录文件列表和删除目录
- 常见字符编码 java
- MyBatis Criteria使用 OffsetLimitInterceptor.java分页报错
- 常用的正则表达式-收藏版
- 读取excel内容在网页上显示出来
- 开课吧Java课堂:如何使用迭代函数
- mysql服务的注册,启动、停止、注销。 [delphi代码实现]
- Git的学习笔记(一)
- Python深度学习:Python数据处理及可视化(读书笔记)
- 《SQL 入门经典》读书笔记(1)
- java代码生成UUID以及在线UUID生成器
- access建立er图_关于ER图的快速生成 | 学步园
- SSD性能怎么测?看这一篇就够了!
- PHP生成二维码与识别二维码,jq生成二维码
- python-jieba库
- vue 引入液晶数字字体
- 极域电子教室功能讲解-电子教室
热门文章
- 兰空图床(lsky-pro)V2.1的自动删除全部图片
- Pytorch基础知识(15)基于PyTorch的多标签图像分类
- 6/4 金汇金融杭州分公司面试
- 记一次ubuntu系统崩溃的修复
- Pytorch中backward函数
- Java如何制作带表格的word文档
- surfacecontrol.java_简单说说JAVA层中Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之间的关系...
- 11 的新增的String的处理方法
- 计算机怎么加网关命令,默认网关怎么设置,教您默认网关怎么设置
- 地下城勇士 DNF 资源分析