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

80

package 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

版权声明:本文(即:原文链接:https://www.qin1qin.com/catagory/19809/)内容由互联网用户自发投稿贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 630367839@qq.com 举报,一经查实,本站将立刻删除。

(0)
上一篇 2022年9月7日 上午11:17
下一篇 2022年9月7日 上午11:17
软件定制开发公司

相关阅读

发表回复

登录后才能评论
通知:禁止投稿所有关于虚拟货币,币圈类相关文章,发现立即永久封锁账户ID!