利用MyBatis实现分页

  • 分页介绍
  • 分页的sql语句实现
  • 在Java中描述并处理分页
  • 获取每页数据
  • MyBatis映射文件中的操作
  • 在Servlet中的响应处理
  • 发送分页请求
  • Servlet响应请求
  • 结尾


分页介绍

我们可以在各个应用app或者网页上看到分页,分页也是数据展现的一种重要形式。
分页在开发中通常用原生的SQL来实现分页功能。分页所需要的数据通常有(当前页码,总记录数,总页数,每页大小,当前页数据(List))。总页数是根据总记录数与每页大小运算得来的。会把这些数据获取后再封装成分页的工具类对象。

分页的sql语句实现

我们在分页的页面可以看到每一页的数据都是一次查询,每一页的数据量都是固定的,用sql语句将数据分页本质就是分多次将其数据查询出来

select * from table limit 0,3	--mysql的实现

上面就将数据表的从第一条数据开始,往后查询三条数据的结果集显示出来了,我们再来看一下分页的sql语句变化过程:

select * from table limit 0,3 --第一页
select * from table limit 3,3 --第二页
select * from table limit 6,3 --第三页
select * from table limit 9,3 --第四页

从上面就可以看到,查出来的数据的每一页都是3笔,现在我们来列出起始偏移的规律

0,3 -->	0*3 = 0
3,3 --> 1*3 = 3
6,3 --> 2*3 = 6
9,3 -->	3*3 = 9

我们可以通过分析发现其中的运算系数规律,比如变化的0,1,2,3将之与每页的页数相乘就可以得出每一页的起始数据位置,而不与其上一页数据重叠。
这时基本可以开始编写代码了,但是我们经过思考会发现人们通常的数数习惯会从1开始数,所以我们最终列出的起始偏移量公式为:(当前页码-1)x每页显示的数据量:

0,3 -->	(1-1)*3 = 0
3,3 --> (2-1)*3 = 3
6,3 --> (3-1)*3 = 6
9,3 -->	(4-1)*3 = 9

那么最后写进代码的sql语句为:

select * from table limit (当前页码-1)*每页显示的数据量,页面数据量

在Java中描述并处理分页

我们可以把所有的分页数据全部封装,为了通用,工具做成泛型类。

import java.util.List;

public class PageUtil<T> {
   /**
    * 当前页
    */
	private int pageIndex;
	/**
	 * 每页大小
	 */
	private int pageSize;
	/**
	 * 总记录数
	 */
	private int totalCount;
	
	/**
	 * 总页数,可以通过每页大小和总记录数运算得来
	 */
	private int totalPageNum;
	/**
	 * 当前页的数据
	 */
	private List<T> list;
	
	public int getPageIndex() {
		return pageIndex;
	}
	
	public void setPageIndex(int pageIndex) {
		this.pageIndex = pageIndex;
	}
	
	public int getPageSize() {
		return pageSize;
	}
	
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}
	
	public int getTotalCount() {
		return totalCount;
	}
	
	public void setTotalCount(int totalCount) {
		this.totalCount = totalCount;
	}
	
	public int getTotalPageNum() {
		return totalPageNum;
	}
	
	public void setTotalPageNum(int totalPageNum) {
		this.totalPageNum = totalPageNum;
	}
	
	public List<T> getList() {
		return list;
	}
	
	public void setList(List<T> list) {
		this.list = list;
	}	
}

这个类对当前页码、每页大小、总记录数、总页数、每页的所有数据进行了简单封装,今后我们对分页进行实现就会省很多重复代码
下面就来解决这个类中的获取每页所有数据进行一个讲解

获取每页数据

/**
	 * 这个方法将当前页码与页面大小作为参数进行传递,因为这两个参数是关键数据
	 */
	public PageUtil<User> getUserList(int currentPageNo, int pageSize) {
		//分页工具类
		PageUtil<User> p = new PageUtil<>();
		int rowCount = 0;  //总记录数
		List<User> userList = null;
		//这句代码会在下篇文章中讲到,他的目的就是获取与数据库的会话(连接)
		SqlSession session = MybatisUtil.getSqlSession();		 
		try {
			//利用MyBatis对接口进行实现
			UserDao dao = session.getMapper(UserDao.class);	
			//获取总数据量,后面会讲到		
			rowCount = dao.getUserCount();
			//参数比较多,可以封装成Map传递,也可以用工具类对象传递
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("currentPageNo", (currentPageNo-1)*pageSize);
			map.put("pageSize", pageSize);
			//获取分页的数据,后面会讲到
			userList = dao.getUserList(map);
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			//关闭会话
			session.close();
		}		
		//从第一个参数获取的当前页码currentPageNo
		p.setPageIndex(currentPageNo);
		//从数据库中获取的总数据量rowCount
		p.setTotalCount(rowCount);
		//从第二个参数获取的每个页面大小pageSize
		p.setPageSize(pageSize); 
		//运算出总页数
		if(rowCount%pageSize ==0)
			//如果总数据量刚好被当前页面大小整除,那就可以直接相除算出页数
			p.setTotalPageNum(rowCount/pageSize);
		else {
			//如果总数据量不能被当前页面大小整除,那就相除后再加上1,这样能保证
			//多余的数据页面会显示出来
			p.setTotalPageNum(rowCount/pageSize+1);
		}
		//当前页的数据
		p.setList(userList);
		
		//返回分页所有的数据。
		return p;
	}

这个方法对数据进行了处理,以后获取分页数据时就不用再处理一些繁琐的数据了,直接调用这个方法获取数据就可以了

MyBatis映射文件中的操作

<select id="getUserCount" resultType="int">
		select count(1) from User
	</select>

	<select id="getUserList" parameterType="map" resultType="User">
		select * from user
		limit #{currentPageNo},#{pageSize}
	</select>

可以看到select标签中parameterType值为map,这就对应着这个方法的形参的类型Map,所以其中的currentPageNo与pageSize都是Map中的键所对应的值。

在Servlet中的响应处理

现在我们可以在Servlet中响应前端的分页操作

mybatais resultMap collection 分页问题_数据

当我们点击下一页或点击页码时发送请求给到Servlet,现在我们来看响应是如何给到前端页面以及前端页面是如何请求Servlet的

发送分页请求

前端页面我们通过ajax请求后端Servlet

function pageFun(PageNum) {
		$.ajax({
				   type: "get",
				   url: "/Project/UserServlet",
				   data: {name: "userPage", index: PageNum},
				   dataType: "json",
				   success: function (data) {
					   $(data).each(function () {
						  $("#tab").append("<tr><td>"+this.UserName+"</td></tr>");
					   })
				   },
				   error: function () {
					   alert("FBI WARING");
				   }
			   })
	}

当我们点击下一页或者直接点击页码就会触发该pageFun的方法,并动态的响应到网页中。

Servlet响应请求

UserService service = new UserServiceImpl();
int pageIndex = 1;  //默认是第1页
if(request.getParameter("index")!=null) {
	pageIndex = Integer.parseInt(request.getParameter("index"));
}
PageUtil<User> page = service.getUserList(pageIndex, 3);
String pageJson = JSON.toJSONString(page.list);
response.getWrite().print(pageJson);

这里利用了Json将集合发送到前端遍历显示分页内容,在这里我只着重介绍分页的后端功能实现,对于前端的设计以及前后端交互我只做出粗略的演示。