各位用户为了找寻关于MyBatis拦截器实现分页功能的实现方法的资料费劲了很多周折。这里教程网为您整理了关于MyBatis拦截器实现分页功能的实现方法的相关资料,仅供查阅,以下为您介绍关于MyBatis拦截器实现分页功能的实现方法的详细内容
MyBatis拦截器实现分页功能的实现方法
前言:
首先说下实现原理。使用拦截器拦截原始的sql,然后加上分页查询的关键字和属性,拼装成新的sql语句再交给mybatis去执行。
除了业务代码之外,需要写的东西不多,提几个关键的:
1、分页对象Page类。给该对象设置一个当前页数(前端给)、总记录数(拦截器内赋值)2个参数,他就能帮你计算出分页sql语句用的2个参数。
? 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/**
* 分页对应的实体类
*/
public
class
Page {
/**
* 总条数
*/
private
int
totalNumber;
/**
* 当前第几页
*/
private
int
currentPage;
/**
* 总页数
*/
private
int
totalPage;
/**
* 每页显示条数
*/
private
int
pageNumber =
5
;
/**
* 数据库中limit的参数,从第几条开始取
*/
private
int
dbIndex;
/**
* 数据库中limit的参数,一共取多少条
*/
private
int
dbNumber;
/**
* 根据当前对象中属性值计算并设置相关属性值
*/
public
void
count() {
// 计算总页数
int
totalPageTemp =
this
.totalNumber /
this
.pageNumber;
int
plus = (
this
.totalNumber %
this
.pageNumber) ==
0
?
0
:
1
;
totalPageTemp = totalPageTemp + plus;
if
(totalPageTemp <=
0
) {
totalPageTemp =
1
;
}
this
.totalPage = totalPageTemp;
// 设置当前页数
// 总页数小于当前页数,应将当前页数设置为总页数
if
(
this
.totalPage <
this
.currentPage) {
this
.currentPage =
this
.totalPage;
}
// 当前页数小于1设置为1
if
(
this
.currentPage <
1
) {
this
.currentPage =
1
;
}
// 设置limit的参数
this
.dbIndex = (
this
.currentPage -
1
) *
this
.pageNumber;
this
.dbNumber =
this
.pageNumber;
}
public
int
getTotalNumber() {
return
totalNumber;
}
public
void
setTotalNumber(
int
totalNumber) {
this
.totalNumber = totalNumber;
this
.count();
}
public
int
getCurrentPage() {
return
currentPage;
}
public
void
setCurrentPage(
int
currentPage) {
this
.currentPage = currentPage;
}
public
int
getTotalPage() {
return
totalPage;
}
public
void
setTotalPage(
int
totalPage) {
this
.totalPage = totalPage;
}
public
int
getPageNumber() {
return
pageNumber;
}
public
void
setPageNumber(
int
pageNumber) {
this
.pageNumber = pageNumber;
this
.count();
}
public
int
getDbIndex() {
return
dbIndex;
}
public
void
setDbIndex(
int
dbIndex) {
this
.dbIndex = dbIndex;
}
public
int
getDbNumber() {
return
dbNumber;
}
public
void
setDbNumber(
int
dbNumber) {
this
.dbNumber = dbNumber;
}
}
2、关键的拦截器实现
? 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 80package
com.imooc.interceptor;
import
java.sql.Connection;
import
java.sql.PreparedStatement;
import
java.sql.ResultSet;
import
java.util.Map;
import
java.util.Properties;
import
org.apache.ibatis.executor.parameter.ParameterHandler;
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.DefaultReflectorFactory;
import
org.apache.ibatis.reflection.MetaObject;
import
org.apache.ibatis.reflection.SystemMetaObject;
import
com.imooc.entity.Page;
/**
* 分页拦截器
*
* @author Skye
*
*/
@Intercepts
({
@Signature
(type = StatementHandler.
class
, method =
"prepare"
, args = { Connection.
class
, Integer.
class
}) })
public
class
PageInterceptor
implements
Interceptor {
public
Object intercept(Invocation invocation)
throws
Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,
SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,
new
DefaultReflectorFactory());
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue(
"delegate.mappedStatement"
);
//通过MetaObject元数据取得方法名id:com.XXX.queryMessageListByPage
String id = mappedStatement.getId();
//匹配在mybatis中定义的与分页有关的查询id
if
(id.matches(
".+ByPage$"
)) {
//BoundSql中有原始的sql语句和对应的查询参数
BoundSql boundSql = statementHandler.getBoundSql();
Map<String, Object> params = (Map<String, Object>) boundSql.getParameterObject();
Page page = (Page) params.get(
"page"
);
String sql = boundSql.getSql();
String countSql =
"select count(*)from ("
+ sql +
")a"
;
Connection connection = (Connection) invocation.getArgs()[
0
];
PreparedStatement countStatement = connection.prepareStatement(countSql);
ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue(
"delegate.parameterHandler"
);
parameterHandler.setParameters(countStatement);
ResultSet rs = countStatement.executeQuery();
if
(rs.next()) {
//为什么是getInt(1)? 因为数据表的列是从1开始计数
page.setTotalNumber(rs.getInt(
1
));
System.out.println(
"拦截器得知page的记录总数为:"
+ page.getTotalNumber());
}
String pageSql = sql +
" limit "
+ page.getDbIndex() +
","
+ page.getDbNumber();
metaObject.setValue(
"delegate.boundSql.sql"
, pageSql);
}
return
invocation.proceed();
}
/**
* @param target
* 被拦截的对象
*/
public
Object plugin(Object target) {
// 如果将拦截器类比喻为代购票的公司,那this就是代购业务员(进入方法前是无代理购票能力业务员,进入后成为有代理能力的业务员)
// 通过注解获取拦截目标的信息,如果不符合拦截要求就返回原目标,如果符合则使用动态代理生成代理对象
return
Plugin.wrap(target,
this
);
}
public
void
setProperties(Properties properties) {
// TODO Auto-generated method stub
}
}
3、mybatis-config.xml里面注册自己写的拦截器
? 1 2 3 4 5<!-- 自定义的分页拦截器 -->
<plugins>
<plugin interceptor=
"你写的拦截器全类名"
>
</plugin>
</plugins>
Dao层相关的mapper.xml里面的sql语句不用做改动。
4、前端需要给后端一个显示哪一页的参数,通过service层组装查询参数之后交给MyBatis去查分页数据,我定义的分页DAO接口返回的数据是一个list,包含了分页查询结果。前端可以用jquery_pagination插件去实现分页的展示,具体去官方github看怎么设置吧。
? 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<!--pagination需要的脚本-->
<%
// 获取请求的上下文
String context = request.getContextPath();
%>
<link href=
"../css/pagination.css"
rel=
"external nofollow"
rel=
"stylesheet"
type=
"text/css"
/>
<script type=
"text/javascript"
src=
"../js/jquery-1.11.3.js"
></script>
<script type=
"text/javascript"
src=
"../js/jquery.pagination.js"
></script>
<script type=
"text/javascript"
>
// 点击分页按钮以后触发的动作
function handlePaginationClick(new_page_index, pagination_container) {
<!--从stuForm表单提交当前页的参数.可以使用restful方式,让springmvc使用
@PathVariable
关键字定义的形参去接。这
2
个参数是分页控件自己提供的,不需要我们去自己找,但是计数从
0
开始,而我们后台分页计数从
1
开始,因此要手动加
1
。 -->
$(
"#stuForm"
).attr(
"action"
,
"你定义的分页查询url/"
+(new_page_index+
1
));
$(
"#stuForm"
).submit();
return
false
;
}
$(function(){
$(
"#News-Pagination"
).pagination(${result.totalRecord}, {
items_per_page:${result.pageSize},
// 每页显示多少条记录
current_page:${result.currentPage} -
1
,
// 当前显示第几页数据
num_display_entries:
8
,
// 分页显示的条目数
next_text:
"下一页"
,
prev_text:
"上一页"
,
num_edge_entries:
2
,
// 连接分页主体,显示的条目数
callback:handlePaginationClick(当前页,分页div的id),
//执行的回调函数
load_first_page:
false
//防止页面一直刷新( 这条非常重要!)
});
});
</script>
<!-- 这部分用c:forEach标签打印查询结果的表格-->
<!--分页控件名称-->
<div id=
"News-Pagination"
></div>
写这篇总结的目的是希望形成一个分页功能的整体解决方案(前端+后端都涵盖到)。4月17、18日开始我会写一个小系统将前段时间所学都用上,完了之后会回来更新这篇文章里面不正确的地方。
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
原文链接:http://blog.csdn.net/kaka0509/article/details/70195804