Mybatis分页插件2.0版本发布
来源:互联网 发布:ie修复软件下载 编辑:程序博客网 时间:2024/06/06 00:29
项目地址:http://git.oschina.net/free/Mybatis_PageHelper
软件介绍:http://www.oschina.net/p/mybatis_pagehelper
分页插件示例: http://blog.csdn.net/isea533/article/details/24700339
v2.0更新内容:
- 支持Mybatis缓存,count和分页同时支持(二者同步)
- 修改拦截器签名,拦截Executor,签名如下:
@Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})) - 将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"
);
1
//求count - 重写sql
2
contents.add(
0
,
new
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。
这里通过执行过程中的截图来看一下实际效果:
增加头尾的count语句
执行的sql
后面使用相同的原理修改为分页SQL:
1
//分页sql
2
contents.add(
0
,
new
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
执行的sql
最后执行修改后的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版本发布
- Mybatis分页插件2.0版本发布
- Mybatis分页插件3.1.1版本发布
- Mybatis分页插件3.2.3版本发布
- Mybatis分页插件3.2.3版本发布
- Mybatis分页插件3.1.1版本发布
- Mybatis 分页插件 3.3.0 发布
- Mybatis 分页插件 3.3.0 发布
- mybatis分页/分页插件
- mybatis 分页插件拦截注解不同版本不同的写法
- mybatis分页插件(物理分页)
- mybatis分页插件实现分页
- Mybatis分页插件
- Mybatis分页插件 - 示例
- Mybatis分页插件更新
- mybatis generator 分页插件
- Mybatis分页插件更新
- Mybatis分页插件 - 示例
- 10款精美而实用的HTML5表单(登录、联系和搜索表单)
- cocos2d 游戏开发实战
- 圆的比较
- Android 开发中的多线程编程技术
- DES 加密解密算法的C++实现
- Mybatis分页插件2.0版本发布
- IllegalStateException: Can not perform this action after onSaveInstanceState
- table自定义排序
- 大数据的数据存储与分析
- Android学习——ClickableSpan点击链接事件 改超链接颜色
- DES加密解密的C++源程序
- spring mvc 整合 velocity
- DES加密解密字符串的JAVA实现(lp)
- R语言系列:数据的基本运算