SQL
/*
在分页查询中,有一些常见变量名
pageNo 当前页(页码),默认是1
pageSize 每页展示数据的条数,需求给定
pageCount 共多少页
pageCount=total%pageSize==0?(total/pageSize):(total/pageSize)+1;
total 共多少条数据,select count(id)计算出
*/
-- 假设,每页展示4条
-- 第一页
select * from user limit 0,4
-- 第二页
select * from user limit 4,4
-- 第三页
select * from user limit 8,4
-- 第四页
select * from user limit (pageNo-1)*pageSize,pageSize
分页
技术:
最终要执行出select * from user limit (pageNo-1)*pageSize,pageSize,就可以实现分页
流程:
- 在第一次查全部时开始分页查询
- 且一定是从第一页开始,后续下一页是当前页+1
- 还需要在展示结果处写出分页信息: 总页数,总条数,上一页,下一页
编码:
-
改造之前的代码
-
改造dao层
-
// 1 方法加参数,int pageNo, int pageSize // 2 sql语句加limit @Override public List<House> findHouseAll(int pageNo, int pageSize) { Connection conn = DBUtil.getConnection( ); PreparedStatement ps = null; ResultSet rs = null; ArrayList<House> list = new ArrayList<>( ); try { String sql = "select * from house limit ?,?"; ps = conn.prepareStatement(sql); ps.setInt(1, (pageNo - 1) * pageSize); ps.setInt(2, pageSize); } } }
-
-
改造service
-
// 1 方法加参数,int pageNo, int pageSize List<House> findHouseAll(int pageNo,int pageSize); @Override public List<House> findHouseAll(int pageNo,int pageSize) { HouseDao houseDao = new HouseDaoImpl(); List<House> list = houseDao.findHouseAll(pageNo,pageSize); return list; }
-
-
改造servlet
-
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 固定每页大小 int pageSize = 2; // 接收请求 String pageNoStr = req.getParameter("pageNo"); // 如果请求中没有页码,认为是第一页 if (pageNoStr == null || "".equals(pageNoStr)) { pageNoStr = "1"; } int pageNo = Integer.parseInt(pageNoStr); // 调用业务层 HouseService houseService = new HouseServiceImpl(); // 查询分页数据 List<House> list = houseService.findHouseAll(pageNo,pageSize); // 做出响应 req.setAttribute("list",list); // 跳转至list.jsp req.getRequestDispatcher("/view/house/list.jsp").forward(req,resp); }
到此处已经实现,第一次展现分页
后续,要向页面展现分页数据: 总页数,总条数,上一页,下一页
继续改造代码
-
-
servlet
-
查出总条数,计算出总页数
-
将数据存储,到页面展现
-
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 固定每页大小 int pageSize = 2; // 接收请求 String pageNoStr = req.getParameter("pageNo"); // 如果请求中没有页码,认为是第一页 if (pageNoStr == null || "".equals(pageNoStr)) { pageNoStr = "1"; } int pageNo = Integer.parseInt(pageNoStr); // 调用业务层 HouseService houseService = new HouseServiceImpl(); // 查询分页数据 List<House> list = houseService.findHouseAll(pageNo,pageSize); // 查询数据条数 int total = houseService.count(); // 计算出总页数 int pageCount = total % pageSize == 0 ? total / pageSize : total / pageSize + 1; // 做出响应 req.setAttribute("list",list); // 将分页信息存储,到页面展现 req.setAttribute("total",total);// 总条数 req.setAttribute("pageNo",pageNo);// 当前页 req.setAttribute("pageCount",pageCount);// 总页数 // 跳转至list.jsp req.getRequestDispatcher("/view/house/list.jsp").forward(req,resp); }
-
-
service 需要设置方法count();
-
dao需要设置方法count();
-
@Override public int count() { Connection conn = DBUtil.getConnection( ); PreparedStatement ps = null; ResultSet rs = null; int total = 0; try { String sql = "select count(hid) total from house"; ps = conn.prepareStatement(sql); rs = ps.executeQuery( ); if (rs.next( )) { total = rs.getInt("total"); } } catch (Exception e) { e.printStackTrace( ); } finally { DBUtil.closeAll(rs, ps, conn); } return total; }
-
-
改造页面
-
页面要展现分页信息
-
<div>共有 ${total} 条记录,第 ${pageNo}/${pageCount} 页</div>
-
-
页面做逻辑处理,第一页时不能再点击上一页,最后一页不能再点击下一页
-
<div> <ul class="pagination"> <%-- if判断为true,内部标签就会展现,if判断为false,内部标签会隐藏 --%> <c:if test="${pageNo != 1}"> <li class="paginate_button previous disabled }"> <a href="${pageContext.request.contextPath}/house/list?pageNo=${pageNo - 1}">上一页</a> </li> </c:if> <li class="paginate_button active"><a href="#">1</a></li> <c:if test="${pageNo != pageCount}"> <li class="paginate_button next disabled"> <a href="${pageContext.request.contextPath}/house/list?pageNo=${pageNo + 1}">下一页</a> </li> </c:if> </ul> </div>
-
-
-
自行完成
- 页码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zLcGD6LF-1685693127601)(https://qiushiju-tuchuang.oss-cn-hangzhou.aliyuncs.com/image/%E9%A1%B5%E7%A0%81.gif)]
模糊查询
场景:
查询多个数据
SQL:
select * from house where address like '%航海路%'
模糊查询的时机:
与分页查询全部同时实现.
前端:
- list.jsp设置搜索框
- 设置请求路径(/house/list)
- 点击发送
后台:
-
HouseListServlet接收请求
-
将关键词也发送给service–> service的findHoseAll方法需要再设计第三个参数,接收关键词
-
List<House> findHouseAll(int pageNo,int pageSize,String keyword);
-
dao.findHoseAll方法也设置第三个参数
-
List<House> findHouseAll(int pageNo,int pageSize,String keyword);
-
改造dao,查询的方法方法代码
-
try { // 基础查询 String sql = "select * from house "; // 根据搜索关键词,有关键词就拼接模糊搜索sql if (keyword != null && !"".equals(keyword)) { sql += " where haddress like concat('%',?,'%')"; } // 一定要拼接分页用的limit语句 sql += " limit ?,?"; System.out.println("动态sql = " + sql ); ps = conn.prepareStatement(sql); // 根据模糊搜索的关键词的有无,来决定给几个?赋值 if (keyword != null && !"".equals(keyword)) { ps.setString(1,keyword); ps.setInt(2, (pageNo - 1) * pageSize); ps.setInt(3, pageSize); }else{ ps.setInt(1, (pageNo - 1) * pageSize); ps.setInt(2, pageSize); } System.out.println("预处理后动态sql = " + sql );
-
同理,count()方法需要设置keyword参数,通过关键词查出有多少条数据
-
其余代码不用改变
BUG
- 搜索后,再点下一页是全部数据的下一页不是模糊搜索的下一页
原因: 点击下一页或上一页时,后台没有接收到关键词keyword,所以dao就没有拼接where后sql语句
解决: 在点击下一页时,在路径中拼接上关键词(关键词就需要后台将关键词返回)
-
更新时间问题
是因为数据库设置了[根据当前时间戳更新],取消即可
-
更新回显下拉框问题
<!-- option属性selected是默认选中 -->
<select>
<option selected>1</option>
<option >2</option>
<option>3</option>
</select>
原因: 点击下一页或上一页时,后台没有接收到关键词keyword,所以dao就没有拼接where后sql语句
解决: 在点击下一页时,在路径中拼接上关键词(关键词就需要后台将关键词返回)
-
更新时间问题
是因为数据库设置了[根据当前时间戳更新],取消即可
-
更新回显下拉框问题
<!-- option属性selected是默认选中 -->
<select>
<option selected>1</option>
<option >2</option>
<option>3</option>
</select>