数据的分页查询对于jsp动态网页的开发是非常重要的,很多地方都用的到,如:商品的显示页面,需要分页查询显示商品信息;后台系统的订单管理,也需要分页查询订单信息等等。
1. 数据为什么要进行分页查询?
也许有人会有这样的疑问,我一次性全部查出来不更好吗。但是我们要知道,对于一个网站或者系统来说,它后台的数据库里面是存储着大量的数据的,如果你是一个用户,想要查看这些数据,是觉得像看书一样一页一页的看,想看那一页就看哪一页好,还是我将这成百上千条的数据一起全部查出来让你从头看到尾好。显然是前者给用户带来的体验感要好。就如同我们在手机上逛淘宝一样。第二就是如果我们一次性查询大量的数据不仅效率慢还会给数据库带来负担。
2. 分页查询首先要知道的几个参数以及它们之间的关系
数据库的LIMIT子句:LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是 0(而不是 1)。
如:select * from 表名 limit 0,5
从数据表中第一行开始,往后查询五条数据。
总页数:查询出来的数据一共有多少页
总条数:数据库中总共有多少条要查询的数据
每页的行数:页面每页要显示的行数,这个值一般都是固定的(如上面的5)
开始的行数:数据库从哪一行开始往后查(如上面的0)
当前是第几页:页面当前显示的是第几页
利用三元运算计算出总页数
总页数:总条数%每页的行数==0?总条数/每页的行数:总条数/每页的行数+1
开始的行数=(当前是第几页-1)*每页的行数
limit 开始的行数,每页的行数
3. 功能实现
下面我们就通过订单管理的分页查询来看看数据的分页查询是如何实现的。
3.1 后台controller类
当用户点击分页查询相关按钮后,请求传给后台的controller类来处理。
/**
* @param sess
* @return
* 分页查询所有订单
*/
@RequestMapping("/Order_findAllOrder.do")
public String Order_findAllOrder(String djy,Model m){
int zts=ser.selectCount(); //查询所有订单的总条数
int zys=zts%10==0?zts/10:zts/10+1; //计算总页数,每一页的行数固定为10
if (djy==null) { //获取当前是第几页
djy="1"; //如果获取的为空,则默认为第一页
}
int dcdjy=Integer.valueOf(djy); //强制类型转换当前是第几页为int类型
int limit=(dcdjy-1)*10; //开始的行数
List<Orders> selectLimit = ser.selectLimit(limit); //通过service调用dao层分页查询订单
m.addAttribute("ordersLimit", selectLimit); //设置所查询到订单数据的Model对象
m.addAttribute("zysOrders", zys); //设置总页数Model对象
m.addAttribute("dcdjyOrders", dcdjy); //设置当前第几页Model对象
/*
* 新建一个list集合,利用当前第几页进行相应的编号
* */
List<Integer> list = new ArrayList<Integer>();
for (int i = (dcdjy*10-9); i <= dcdjy*10; i++) {
list.add(i);
}
m.addAttribute("xhList", list);
return "shop/manager/category/listOrders.jsp"; //返回前台jsp页面进行显示
}
3.2 dao层sql语句查询数据库
/**
* @return
* 查询所有订单的总条数
*/
@Select("select count(*) from orders")
public int selectCount();
/**
* @param limit
* @return
* 分页查询订单
*/
@Select("select * from orders limit #{limit},10")
public List<Orders> selectLimit(int limit);
3.3 前台jsp页面显示
<table cellSpacing="1" cellPadding="0" width="100%" align="center" bgColor="#f5fafe" border="0">
<TBODY>
<tr>
<td class="ta_01" align="center" bgColor="#afd1f3">
<strong>订单列表</strong>
</TD>
</tr>
<tr>
<td class="ta_01" align="center" bgColor="#f5fafe">
<table cellspacing="0" cellpadding="1" rules="all"bordercolor="gray" border="1" id="DataGrid1" style="BORDER-RIGHT: gray 1px solid; BORDER-TOP: gray 1px solid; BORDER-LEFT: gray 1px solid; WIDTH: 100%; WORD-BREAK: break-all; BORDER-BOTTOM: gray 1px solid; BORDER-COLLAPSE: collapse; BACKGROUND-COLOR: #f5fafe; WORD-WRAP: break-word">
<tr style="FONT-WEIGHT: bold; FONT-SIZE: 12pt; HEIGHT: 25px; BACKGROUND-COLOR: #afd1f3">
<td align="center" width="18%">
序号
</td>
<td align="center" width="17%">
订单编号
</td>
<td align="center" width="17%">
订单金额
</td>
<td align="center" width="17%">
收货人
</td>
<td align="center" width="17%">
订单状态
</td>
<td align="center" width="17%">
订单详情
</td>
</tr>
<c:if test="${ordersLimit.size()==0 }">
<tr>
<td colspan="6" style="text-align: center;">没有相应的订单记录</td>
</tr>
</c:if>
<c:forEach items="${ordersLimit }" var="u" varStatus="status">
<tr style="FONT-WEIGHT: bold; FONT-SIZE: 12pt; HEIGHT: 25px; BACKGROUND-COLOR: #afd1f3">
<td align="center" width="18%">
${xhList[status.index] }
</td>
<td align="center" width="17%">
${u.oid }
</td>
<td align="center" width="17%">
${u.total }
</td>
<td align="center" width="17%">
${u.name }
</td>
<td align="center" width="17%">
<c:if test="${u.state==3 }"><span style="color: blue;">已付款</span></c:if>
<c:if test="${u.state==1 || u.state==2 ||u.state==4 }">未付款</c:if>
</td>
<td align="center" width="17%">
<a href="${pageContext.request.contextPath}/Order_details.do?oid=${u.oid }">
<input type="button" style="cursor: pointer;" value="订单详情">
</a>
</td>
</tr>
</c:forEach>
<c:if test="${ordersLimit.size()!=0 }">
<tr>
<td colspan="6" style="text-align: center;">
<c:if test="${dcdjyOrders==1}">
<a href="javascript:first()"><</a>
</c:if>
<c:if test="${dcdjyOrders>1}">
<a href="${pageContext.request.contextPath}/Order_findAllOrder.do?djy=${dcdjyOrders-1}"><</a>
</c:if>
<a href="${pageContext.request.contextPath}/Order_findAllOrder.do?djy=1">首页</a>
<c:forEach begin="1" end="${zysOrders}" step="1" var="i">
<c:if test="${i==dcdjyOrders}">
<a href="${pageContext.request.contextPath}/Order_findAllOrder.do?djy=${i}" style="color: red;">${i}</a>
</c:if>
<c:if test="${i!=dcdjyOrders}">
<a href="${pageContext.request.contextPath}/Order_findAllOrder.do?djy=${i}">${i}</a>
</c:if>
</c:forEach>
<a href="${pageContext.request.contextPath}/Order_findAllOrder.do?djy=${zysOrders}">尾页</a>
<c:if test="${dcdjyOrders<zysOrders}">
<a href="${pageContext.request.contextPath}/Order_findAllOrder.do?djy=${dcdjyOrders+1}">></a>
</c:if>
<c:if test="${dcdjyOrders==zysOrders}">
<a href="javascript:last()">></a>
</c:if>
</td>
</tr>
</c:if>
</table>
</td>
</tr>
</TBODY>
</table>
<script type="text/javascript">
function first() {
alert("已经是第一页了");
}
function last() {
alert("已经是最后一页了");
}
</script>
前台jsp页面用c:foreach循环遍历显示Model中的集合对象,页面的下面显示总页数、当前第几页、上一页、下一页等信息,并且可以通过这些按钮或标签发送相应的查询请求。
4. 总结
数据的分页查询其本质就是查询部分数据,通过limit子句来控制select语句返回指定的记录数。这样既实现了高效的查询效率,也增加了用户的体验感。分页查询本身不难,dao层其实就两条sql语句,一条查询总条数,一条进行分页查询。难点就在于controller类中对相关参数的处理,以及前台jsp页面的循环显示与发送相应的请求及参数。
5. 前台页面实现结果