Mybatis分页插件2.0版本发布

项目地址:http://git.oschina.net/free/Mybatis_PageHelper

分页插件示例: http://blog.csdn.net/isea533/article/details/24700339

v2.0更新内容:

  1. 支持Mybatis缓存,count和分页同时支持(二者同步)
  2. 修改拦截器签名,拦截Executor,签名如下:

    @Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))

  3. 将Page类移到外面,方便调用

有位朋友留言说插件不支持缓存,在使用缓存的情况下无法正常运行。

这个问题确实存在,因为缓存是CachingExecutor在v1.0版本中的拦截器之前进行的,也就是说,当查询结果被缓存后,使用缓存的时候是进不到分页插件中的,而且分页插件无法取得返回的结果,因而不能正常运行,既然找到了原因,而且Executor也可以被拦截,我就在想能否直接拦截Executor并且支持缓存。

通过查看源码以及调试,找到一种可行的方法,并且经过多项测试到最后完成,共计4小时,我测试的内容有缓存/不缓存两种情况,以及返回为resultType/resultMap两种情况,共计4种情况下的使用情况。测试仍然不算全面,所以我希望使用该插件的各位朋友遇到问题能及时反馈。

这次更新和前一个版本的实现方法毫无关联,而且也从来没人这么做过,所以有问题请及时反馈,下面说说具体的实现方法。

首先拦截器签名变了:

1 @Intercepts(@Signature(type
= Executor.
class,
2                        method
"query",
3                        args
= {MappedStatement.
class,
4                                Object.class,
5                                RowBounds.class,
6                                ResultHandler.class}))

查看完整代码请点击这里,下面讲一些实现的细节:

1 List<SqlNode>
contents = (List<SqlNode>) msObject.getValue(
"sqlSource.rootSqlNode.contents");

这段代码获取了SqlNode集合,Mybatis要执行的Sql从通过这个集合拼出来了,在第一个版本的中的BoundSql就是通过contents中的内容生成的, 所以这种分页方式绝对是意想不到的,获取这个对象后,做了如下处理:

1 //求count
- 重写sql
2 contents.add(0new TextSqlNode("select
count(0) from ("
));
3 contents.add(new TextSqlNode(")"));

往第一行插入了求count的sql,最后一行加了一个“)”,通过头尾添加的这两个,就让这一个正常的sql语句变成了一个求count的sql,下面这一句代码:

1 Class<?>
resultType = (Class<?>) msObject.getValue(
"resultMaps[0].type");

这一句代码的作用是先把正常的返回值类型保存,然后做了如下修改:

1 msObject.setValue("resultMaps[0].type"int.class);

将返回值改为int类型,用于接收返回的count总数,还有一句很重要的代码:

1 List<ResultMapping>
resultMappings = (List<ResultMapping>) msObject.getValue(
"resultMaps[0].resultMappings");

这里也是先把resultMappings备份,这个值在使用resultMap的情况会对返回结果造成干扰,所以这里先备份,然后用一个空的list去代替:

1 msObject.setValue("resultMaps[0].resultMappings",
EMPTY_RESULTMAPPING);

然后就去执行这个修改后的sql:

01 //查询总数
02 Object
result = 
null;
03 try {
04     result
= invocation.proceed();
05     int totalCount
= Integer.parseInt(((List) result).get(
0).toString());
06     page.setTotal(totalCount);
07     int totalPage
= totalCount / page.getPageSize() + ((totalCount % page.getPageSize() == 
0)
0 1);
08     page.setPages(totalPage);
09 finally {
10     //清理count
sql
11     contents.remove(0);
12     contents.remove(contents.size()
1);
13     //恢复类型
14     msObject.setValue("resultMaps[0].type",
resultType);
15     msObject.setValue("resultMaps[0].resultMappings",
resultMappings);
16 }

因为这里执行了result = invocation.proceed()方法,所以在开启缓存的情况下,该sql也会被缓存,这里将结果totalCount保存到Page,然后在finally中执行了清理sql的方法和恢复类型的方法,这样就又变成了原来的sql。

后面使用相同的原理修改为分页SQL:

1 //分页sql
2 contents.add(0new TextSqlNode("select
* from ( select temp.*, rownum row_id from ( "
));
3 StringBuilder
pageSql = 
new StringBuilder(200);
4 pageSql.append("
) temp where rownum <= "
).append(page.getEndRow());
5 pageSql.append(")
where row_id > "
).append(page.getStartRow());
6 contents.add(new TextSqlNode(pageSql.toString()));

最后执行修改后的sql,保存处理结果:

01 //将执行权交给下一个拦截器
02 try {
03     result
= invocation.proceed();
04 finally {
05     //清理分页sql
06     contents.remove(0);
07     contents.remove(contents.size()
1);
08 }
09 //得到处理结果
10 page.setResult((List)
result);
11 //返回结果
12 return result;

这里仍然不能忘记在finally中清理sql。

通过这种方法,完全使用了Mybatis的内容来操作,而且可以支持缓存,缓存对求count语句来说效果更明显,因为你查看下一页内容的时候不会重复执行count,会使用缓存。而且分页sql和count sql是同步缓存的,所以不用担心数据不一致的情况。而且这种分页方式不影响原方法的单独执行(不分页)。

如果对你有帮助,或者有什么建议欢迎留言!

转载请注明原文地址和作者!

Mybatis分页插件2.0版本发布,布布扣,bubuko.com

时间: 2024-12-15 06:53:47

Mybatis分页插件2.0版本发布的相关文章

Mybatis分页插件

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

Mybatis分页插件-PageHelper的使用

转载:http://blog.csdn.net/u012728960/article/details/50791343 Mybatis分页插件-PageHelper的使用 怎样配置mybatis这里就不提了,我来说说我配置这个分页插件的过程吧. 下载JAR包 分页插件pagehelper.jar: https://oss.sonatype.org/content/repositories/releases/com/github/pagehelper/pagehelper/ http://repo

MyBatis学习总结(17)——Mybatis分页插件PageHelper

如果你也在用Mybatis,建议尝试该分页插件,这一定是最方便使用的分页插件. 分页插件支持任何复杂的单表.多表分页,部分特殊情况请看重要提示. 想要使用分页插件?请看如何使用分页插件. 物理分页 该插件目前支持以下数据库的物理分页: Oracle Mysql MariaDB SQLite Hsqldb PostgreSQL DB2 SqlServer(2005,2008) Informix H2 SqlServer2012 配置dialect属性时,可以使用小写形式: oracle,mysql

基于Mybatis分页插件PageHelper

基于Mybatis分页插件PageHelper 1.分页插件使用 1.POM依赖 PageHelper的依赖如下.需要新的版本可以去maven上自行选择 <!-- PageHelper 插件分页 --><dependency>    <groupId>com.github.pagehelper</groupId>    <artifactId>pagehelper</artifactId>    <version>4.0.

Mybatis分页插件PageHelper的配置和使用方法

http://www.cnblogs.com/kangoroo/p/7998433.html 前言 在web开发过程中涉及到表格时,例如dataTable,就会产生分页的需求,通常我们将分页方式分为两种:前端分页和后端分页. 前端分页 一次性请求数据表格中的所有记录(ajax),然后在前端缓存并且计算count和分页逻辑,一般前端组件(例如dataTable)会提供分页动作. 特点是:简单,很适合小规模的web平台:当数据量大的时候会产生性能问题,在查询和网络传输的时间会很长. 后端分页 在aj

mybatis 分页插件PageHelper3.7.4试用

pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <mo

Mybatis分页插件PageHelper的使用

Mybatis分页插件 - PageHelper支持任何复杂的单表.多表分页.使用方法如下: 1.导入jar包 2.在Maven中添加依赖 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> </dependency> 3.在mybatis配置文件中配置插件 <?xml version="1.

Spring.Net.FrameworkV3.0 版本发布了,感谢大家的支持

Spring.Net.FrameworkV3.0 版本发布了,感谢大家的支持. Spring.Net.Framework,基于.NET的快速信息化系统开发.整合框架,为企业或个人在.NET环境下快速开发系统提供了强大的支持,开发人员不需要开发系统的基础功能和公共模块,框架自身提供了强大的函数库和开发包,开发人员只须集中精力专注于业务部分的开发,因此大大提高开发效率和节约开发成本.框架采用目前最主流的C#语言开发完成,支持多种数据库类型,支持WinForm与Web(用的是现在主流的MVC框架).使

Mybatis分页插件PageHelper使用

一. Mybatis分页插件PageHelper使用  1.不使用插件如何分页: 使用mybatis实现: 1)接口: List<Student> selectStudent(Map<String, Object> map); 2)mapper.xml: <select id="selectStudent" resultMap="BaseResultMap" parameterType="java.util.Map"