写在前边
- 现在的时间:2019-2-3
- MyBatis提供了分页插件
PageHelper
,但对新手来说可能无从下手。 - 所以这个demo中为了更好的理解不使用分页插件,自已写,使用原生的代码更便于理解。
- 使用
SpringBoot
、MyBatis
、MySQL
完成分页的查询用Thymeleaf
显示。
demo下载
- 码云:https://gitee.com/blog_quotes/springboot-page.git
- 所需的数据库在github的
README.md
文件中。
知识预备
参数
为了分页查询与显示 ,我们要设置4个参数:
- 当前页:
currPage
- 每页显示的数据条数:
pageSize
- 数据的总条数:
totalCount
- 总页数:
totalPage
其中总totalPage
是由totalCount
和pageSize
计算出来的,例如共有12条记录,每页显示5条的话共有3页,每页显示6条的话共有2页。
所以totalPage
的计算如下:
if (totalCount % pageSize == 0)
{
totalPage = totalCount / pageSize;
}
else
{
totalPage = totalCount / pageSize + 1;
}
MySQL的limit函数
- 我们都知道
mysql
有个limit
函数可以限制select
语句返回的条数,因此使用mysql
做分页查询异常的简单,只需要控制limit
函数的两个参数即可查询到指定页的数据。 - limit函数的第二个参数是返回的记录数,因此第二个参数很简单,就是
pageSize
;第一个参数起始记录的编号(从0起),例如每页有5条数据,那么第一页的话第一个参数就应该是0,第二页的话应该是5,找寻规律,第一个参数应该是currPage * pageSize - pageSize
。
基本流程
- 前端发送URL请求,将要查询的页(即当前页)传递给后端。例如下边这段代码,第一次进入,查询第一页的数据。
@GetMapping("/toShow")
public String toShow()
{
return "redirect:/selectByPageTest?currPage=1";
}
- 后端接收到参数后为
currPage
、pageSize
、totalCount
赋值,并计算出totalPage
。
/**
* 计算各个参数
*/
public void calc()
{
totalCount = mapper.selectCount();
pageSize = 5;
if (totalCount % pageSize == 0)
{
totalPage = totalCount / pageSize;
}
else
{
totalPage = totalCount / pageSize + 1;
}
}
- 后端调用sql语句查询出当前页的数据集合
data
。
Map<String, Integer> parameter = new HashMap<>(2);
parameter.put("begin", currPage * pageSize - pageSize);
parameter.put("num", pageSize);
List<People> data = mapper.selectPage(parameter);
- 后端将
currPage
、totalCount
、list
返回给前端(data
是要显示的数据必然要返回,返回currPage
与totalCount
是为了完成“下一页”“跳转到**页”等功能)
model.addAttribute("data", data); //前端要展示的数据
model.addAttribute("currPage", currPage); //当前页
model.addAttribute("totalPage", totalPage); //总页数
- 前端页面进行展示
<body>
<table border="2px">
<tr>
<th>ID</th>
<th>姓名</th>
</tr>
<tr th:each="people : ${data}">
<th th:text="${people.id}"></th>
<th th:text="${people.name}"></th>
</tr>
</table>
<br/>
<a th:href="@{ /selectByPageTest(currPage=1) }">首页</a>
<a th:href="@{/selectByPageTest(currPage=${currPage}-1)}">上一页</a> <!--这两个currPage要分清,第一个是要传给后端的,也就是上一页的页数,第二个是后端传过来的,也就是这一页的页灵长-->
<span th:each="i : ${ #numbers.sequence(1,totalPage) }">
<a th:text="${i}" th:href="@{ /selectByPageTest(currPage=${i}) }"></a>
</span>
<a th:href="@{/selectByPageTest(currPage=${currPage}+1)}">下一页</a>
<a th:href="@{ /selectByPageTest(currPage=${totalPage}) }">尾页</a>
<div>
<form action="/selectByPageTest" method="get">
跳转到第
<input type="number" name="currPage" />
页
<input type="submit" value="跳转"/>
</form>
</div>
</body>
其他
- 因为一个项目中可能不止一种数据需要分页查询,此此我们可以在后端将分页查询封装成一个类,在这个类的构造方法中完成这四个参数的赋值与计算。
- 其实个类的每一个对象,就代表了一页,只不过这里没有把这页的数据放进来,类此可以说它是一个“页类”。
public class PageBean
{
private int currPage; //当前页数
private int pageSize; //每页显示记录数
private int totalCount; //总记录数
private int totalPage; //总页数
/**
* 构造函数
* 四个参数中这三个需要手动注入,总页数是计算出来的
* 只提供 getter 方法, 不提供 setter 方法 构造函数行使了 setter 方法的功能
* @param currPagePara
* @param pageSizePara
* @param totalCountPara
*/
public PageBean(int currPagePara, int pageSizePara, int totalCountPara)
{
currPage = currPagePara;
pageSize = pageSizePara;
totalCount = totalCountPara;
if (totalCount % pageSize == 0)
{
totalPage = totalCount / pageSize;
}
else
{
totalPage = totalCount / pageSize + 1;
}
if (currPage <= 0)
{
currPage = 1;
}
if (currPage >= totalPage + 1)
{
currPage = totalPage;
}
}
public int getCurrPage()
{
return currPage;
}
public int getPageSize()
{
return pageSize;
}
public int getTotalCount()
{
return totalCount;
}
public int getTotalPage()
{
return totalPage;
}
}