- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章自己动手写的mybatis分页插件(极其简单好用)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
刚开始项目,需要用到mybatis分页,网上看了很多插件,其实实现原理基本都大同小异,但是大部分都只给了代码,注释不全,所以参考了很多篇文章(每篇文章偷一点代码,评出来自己的,半抄袭),才自己模仿着写出了一个适合自己项目的分页插件,话不多说,直接上代码,相比大部分文章,注释算很完整了 。
最重要的拦截器 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
package
com.dnkx.interceptor;
import
java.sql.*;
import
java.util.HashMap;
import
java.util.Properties;
import
org.apache.ibatis.executor.resultset.ResultSetHandler;
import
org.apache.ibatis.executor.statement.StatementHandler;
import
org.apache.ibatis.mapping.BoundSql;
import
org.apache.ibatis.mapping.MappedStatement;
import
org.apache.ibatis.plugin.Interceptor;
import
org.apache.ibatis.plugin.Intercepts;
import
org.apache.ibatis.plugin.Invocation;
import
org.apache.ibatis.plugin.Plugin;
import
org.apache.ibatis.plugin.Signature;
import
org.apache.ibatis.reflection.MetaObject;
import
org.apache.ibatis.reflection.SystemMetaObject;
import
com.dnkx.pojo.Page;
/**
*
* 分页拦截器,用于拦截需要进行分页查询的操作,然后对其进行分页处理。
* 利用拦截器实现Mybatis分页的原理:
* 要利用JDBC对数据库进行操作就必须要有一个对应的Statement对象,Mybatis在执行Sql语句前就会产生一个包含Sql语句的Statement对象,而且对应的Sql语句
* 是在Statement之前产生的,所以我们就可以在它生成Statement之前对用来生成Statement的Sql语句下手。在Mybatis中Statement语句是通过RoutingStatementHandler对象的
* prepare方法生成的。所以利用拦截器实现Mybatis分页的一个思路就是拦截StatementHandler接口的prepare方法,然后在拦截器方法中把Sql语句改成对应的分页查询Sql语句,之后再调用
* StatementHandler对象的prepare方法,即调用invocation.proceed()。
* 对于分页而言,在拦截器里面我们还需要做的一个操作就是统计满足当前条件的记录一共有多少,这是通过获取到了原始的Sql语句后,把它改为对应的统计语句再利用Mybatis封装好的参数和设
* 置参数的功能把Sql语句中的参数进行替换,之后再执行查询记录数的Sql语句进行总记录数的统计。
*
* 解释一下插件中可能要用到的几个类:
* MetaObject:mybatis提供的一个基于返回获取属性值的对象的类
* BoundSql : 在这个里面可以获取都要执行的sql和执行sql要用到的参数
* MappedStatement : 这个可以得到当前执行的sql语句在xml文件中配置的id的值
* RowBounds : 是mybatis内存分页要用到的。
* ParameterHandler : 是mybatis中用来替换sql中?出现的值的.
*
* @author 李小拐 2016年11月9日 10:59:04
*/
@Intercepts
({
@Signature
(type=StatementHandler.
class
,method=
"prepare"
,args={Connection.
class
}),
@Signature
(type = ResultSetHandler.
class
, method =
"handleResultSets"
, args = {Statement.
class
})
})
public
class
PageInterceptor
implements
Interceptor{
//拦截分页关键字
private
static
final
String SELECT_ID=
"page"
;
//插件运行的代码,它将代替原有的方法,要重写最重要的intercept了
@Override
public
Object intercept(Invocation invocation)
throws
Throwable {
if
(invocation.getTarget()
instanceof
StatementHandler) {
//这里我们有一个设定 如果查询方法含有Page 就进行分页 其他方法无视
//所以就要获取方法名
StatementHandler statementHandler=(StatementHandler)invocation.getTarget();
MetaObject metaObject=SystemMetaObject.forObject(statementHandler);
MappedStatement mappedStatement=(MappedStatement)metaObject.getValue(
"delegate.mappedStatement"
);
String selectId=mappedStatement.getId();
String methorName=selectId.substring(selectId.lastIndexOf(
"."
)+
1
).toLowerCase();
//然后判断下 如果含有Page 就获取sql
if
(methorName.contains(SELECT_ID)){
BoundSql boundSql=(BoundSql)metaObject.getValue(
"delegate.boundSql"
);
//分页参数作为参数对象parameterObject的一个属性
String sql=boundSql.getSql();
System.out.println(
"获取到的sql:"
+sql);
HashMap<String, Object> map=(HashMap<String, Object>)(boundSql.getParameterObject());
//Page page=(Page)(boundSql.getParameterObject());
Page page=(Page)map.get(
"page"
);
// 重写sql
String countSql=concatCountSql(sql);
String pageSql=concatPageSql(sql,page);
// System.out.println("重写的 count sql :"+countSql);
System.out.println(
"重写的 select sql :"
+pageSql);
Connection connection = (Connection) invocation.getArgs()[
0
];
PreparedStatement countStmt =
null
;
ResultSet rs =
null
;
int
totalCount =
0
;
try
{
countStmt = connection.prepareStatement(countSql);
rs = countStmt.executeQuery();
if
(rs.next()) {
totalCount = rs.getInt(
1
);
}
}
catch
(SQLException e) {
System.out.println(
"Ignore this exception"
+e);
}
finally
{
try
{
rs.close();
countStmt.close();
}
catch
(SQLException e) {
System.out.println(
"Ignore this exception"
+ e);
}
}
metaObject.setValue(
"delegate.boundSql.sql"
, pageSql);
//绑定count
page.setNumCount(totalCount);
}
}
return
invocation.proceed();
}
// 拦截类型StatementHandler,重写plugin方法
@Override
public
Object plugin(Object target) {
if
(target
instanceof
StatementHandler) {
return
Plugin.wrap(target,
this
);
}
else
{
return
target;
}
}
@Override
public
void
setProperties(Properties properties) {
}
//改造sql
public
String concatCountSql(String sql){
//StringBuffer sb=new StringBuffer("select count(*) from ");
/*sql=sql.toLowerCase();
if(sql.lastIndexOf("order")>sql.lastIndexOf(")")){
sb.append(sql.substring(sql.indexOf("from")+4, sql.lastIndexOf("order")));
}else{
sb.append(sql.substring(sql.indexOf("from")+4));
}*/
StringBuffer sb=new StringBuffer();
sql=sql.toLowerCase();
if(sql.lastIndexOf("order")>0){
sql=sql.substring(0,sql.indexOf("order"));
}
sb.append("select count(*) from ("+sql+") tmp");
return sb.toString();
}
public String concatPageSql(String sql,Page page){
StringBuffer sb=new StringBuffer();
sb.append(sql);
sb.append(" limit ").append(page.getPageBegin()).append(" , ").append(page.getPageSize());
return sb.toString();
}
}
分页对象Page类
[java] view plain copy
package com.dnkx.pojo;
import java.util.HashMap;
import java.util.Map;
/**
*
* 分页查询辅助类
* @author 李小拐 2016年11月9日 13:55:37
*/
public
class
Page {
//----------分页-----------
private
int
pageSize;
//每页显示条数
private
int
pageCurrentPage;
//第几页
private
int
pageBegin;
//开始位置
private
int
numCount;
//总条数
private
int
pageTotal;
//总条数
private
String orderField =
""
;
//控制排序页面显示的
private
String orderDirection =
""
;
public
Page(){
}
public
Page(
int
pageSize,
int
pageCurrentPage) {
super
();
this
.pageSize = pageSize;
this
.pageCurrentPage = pageCurrentPage;
}
public
Page(Map<String, String> map){
if
(map.get(
"pageNum"
)!=
null
){
this
.setPageCurrentPage(
this
.pageCurrentPage = Integer.parseInt(map.get(
"pageNum"
)));
//要查询的页数
}
else
{
this
.setPageCurrentPage(
1
);
//设置初始值
}
if
(map.get(
"numPerPage"
)!=
null
){
this
.setPageSize(Integer.parseInt(map.get(
"numPerPage"
)));
//每页显示条数
}
else
{
this
.setPageSize(
5
);
//设置初始值
}
if
(map.get(
"orderField"
)!=
null
){
this
.setOrderField(map.get(
"orderField"
));
}
if
(map.get(
"orderDirection"
)!=
null
){
this
.setOrderDirection(map.get(
"orderDirection"
));
}
}
public
int
getPageCurrentPage() {
return
pageCurrentPage;
}
public
void
setPageCurrentPage(
int
pageCurrentPage) {
this
.pageCurrentPage = pageCurrentPage;
}
public
int
getNumCount() {
return
numCount;
}
public
void
setNumCount(
int
numCount) {
this
.numCount = numCount;
}
public
int
getPageTotal() {
return
(numCount%pageSize>
0
)?(numCount/pageSize+
1
):(numCount/pageSize);
}
public
void
setPageTotal(
int
pageTotal) {
this
.pageTotal = pageTotal;
}
public
int
getPageSize() {
return
pageSize;
}
public
void
setPageSize(
int
pageSize) {
this
.pageSize = pageSize;
}
public
int
getPageBegin() {
return
pageSize*(pageCurrentPage-
1
);
}
public
void
setPageBegin(
int
pageBegin) {
this
.pageBegin = pageBegin;
}
public
String getOrderField() {
return
orderField;
}
public
void
setOrderField(String orderField) {
this
.orderField = orderField;
}
public
String getOrderDirection() {
return
orderDirection;
}
public
void
setOrderDirection(String orderDirection) {
this
.orderDirection = orderDirection;
}
public
static
Page getPage(
int
pageSize,
int
pageCurrentPage){
return
new
Page(pageSize,pageCurrentPage);
}
public
static
Page getPage(Map map){
return
new
Page(map);
}
}
|
Controller里面调用方式 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public
String list(HttpServletRequest request) {
long
a=System.currentTimeMillis();
HashMap<String,Object> map=GetRequestMap.getMap(request);
//自己封装的方法,取request的参数
Page page= Page.getPage(map);
//初始化page
map.put(
"page"
, page);
//把page对象放入参数集合(这个map是mybatis要用到的,包含查询条件,排序,分页等)
//控制排序页面显示的
map.put(map.get(
"orderField"
)+
""
, map.get(
"orderDirection"
));
List<Employee> list=employeeService.getListPage(map);
request.setAttribute(
"emlist"
, list);
request.setAttribute(
"page"
, page);
request.setAttribute(
"map"
, map);
//取page相关属性
page.getNumCount();
//总条数
page.getPageTotal();
//总页数
long
b=System.currentTimeMillis();
System.out.println(
"---------耗时:"
+(b-a)+
"ms"
);
return
"basic/employee_list"
;
}
|
最后,spring里面配置插件 。
1
2
3
4
5
6
7
8
9
10
|
<bean id=
"PageInterector"
class
=
"com.dnkx.interceptor.PageInterceptor"
></bean>
<!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
<bean id=
"sqlSessionFactory"
class
=
"org.mybatis.spring.SqlSessionFactoryBean"
>
<property name=
"dataSource"
ref=
"dataSource"
/>
<!-- 自动扫描mapping.xml文件 -->
<property name=
"mapperLocations"
value=
"classpath:com/dnkx/mapping/*.xml"
></property>
<property name=
"plugins"
>
<ref bean=
"PageInterector"
/>
</property>
</bean>
|
好了,到此结束,本文仅供参考!也期待大神提意见 。
原文链接:http://blog.csdn.net/yttea/article/details/53139796 。
最后此篇关于自己动手写的mybatis分页插件(极其简单好用)的文章就讲到这里了,如果你想了解更多关于自己动手写的mybatis分页插件(极其简单好用)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在努力实现以下目标, 假设我有字符串: ( z ) ( A ( z ) ( A ( z ) ( A ( z ) ( A ( z ) ( A ) ) ) ) ) 我想编写一个正则
给定: 1 2 3 4 5 6
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
大家好,我卡颂。 Svelte问世很久了,一直想写一篇好懂的原理分析文章,拖了这么久终于写了。 本文会围绕一张流程图和两个Demo讲解,正确的食用方式是用电脑打开本文,跟着流程图、Demo一
身份证为15位或者18位,15位的全为数字,18位的前17位为数字,最后一位为数字或者大写字母”X“。 与之匹配的正则表达式: ?
我们先来最简单的,网页的登录窗口; 不过开始之前,大家先下载jquery的插件 本人习惯用了vs2008来做网页了,先添加一个空白页 这是最简单的的做法。。。先在body里面插入 <
1、MySQL自带的压力测试工具 Mysqlslap mysqlslap是mysql自带的基准测试工具,该工具查询数据,语法简单,灵活容易使用.该工具可以模拟多个客户端同时并发的向服务器发出
前言 今天大姚给大家分享一款.NET开源(MIT License)、免费、简单、实用的数据库文档(字典)生成工具,该工具支持CHM、Word、Excel、PDF、Html、XML、Markdown等
Go语言语法类似于C语言,因此熟悉C语言及其派生语言( C++、 C#、Objective-C 等)的人都会迅速熟悉这门语言。 C语言的有些语法会让代码可读性降低甚至发生歧义。Go语言在C语言的
我正在使用快速将 mkv 转换为 mp4 ffmpeg 命令 ffmpeg -i test.mkv -vcodec copy -acodec copy new.mp4 但不适用于任何 mkv 文件,当
我想计算我的工作簿中的工作表数量,然后从总数中减去特定的工作表。我错过了什么?这给了我一个对象错误: wsCount = ThisWorkbook.Sheets.Count - ThisWorkboo
我有一个 perl 文件,用于查看文件夹中是否存在 ini。如果是,它会从中读取,如果不是,它会根据我为它制作的模板创建一个。 我在 ini 部分使用 Config::Simple。 我的问题是,如果
尝试让一个 ViewController 通过标准 Cocoa 通知与另一个 ViewController 进行通信。 编写了一个简单的测试用例。在我最初的 VC 中,我将以下内容添加到 viewDi
我正在绘制高程剖面图,显示沿路径的高程增益/损失,类似于下面的: Sample Elevation Profile with hand-placed labels http://img38.image
嗨,所以我需要做的是最终让 regStart 和 regPage 根据点击事件交替可见性,我不太担心编写 JavaScript 函数,但我根本无法让我的 regPage 首先隐藏。这是我的代码。请简单
我有一个非常简单的程序来测量一个函数花费了多少时间。 #include #include #include struct Foo { void addSample(uint64_t s)
我需要为 JavaScript 制作简单的 C# BitConverter。我做了一个简单的BitConverter class BitConverter{ constructor(){} GetBy
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
我是 Simple.Data 的新手。但我很难找到如何进行“分组依据”。 我想要的是非常基本的。 表格看起来像: +________+ | cards | +________+ | id |
我现在正在开发一个 JS UDF,它看起来遵循编码。 通常情况下,由于循环计数为 2,Alert Msg 会出现两次。我想要的是即使循环计数为 3,Alert Msg 也只会出现一次。任何想法都
我是一名优秀的程序员,十分优秀!