模糊查询结果的分页实现
一、目标需求
- 数据列表下展示分页框,点击项包括
上一页
,下一页
和具体页码
。点击按钮实现相应的页面跳转。- 同时要显示数据总数,总页数和当前页数
- 查询可以选择关键字类别
二、实现过程注意事项
- 模糊查询后显示查询结果列表,页码等信息需要随之改变
- 查询后点击下一页和上一页需要在查询结果列表中跳转,而不能跳回全部数据列表中
- 不输入查询关键字的情况下点击查询,默认查询全部数据
- 在第一页不需要上一页功能,最后一页不需要下一页功能
- 浏览到某一页时,相应的页码按钮应该有选中样式
三、具体实现
下面代码中部分关键字或变量解释
feild——查询关键词字段(类型)
keyword——输入的查询关键字
pageNo——当前页
pageCount——总页数
pageSize——每页展示的数据数量
house——数据库中的表名
3.1 前端界面(JSP实现——代码不全,理解实现方式即可)
3.1.1模糊查询部分
预计效果
这里选择了用下拉框来选择关键词字段
这个功能在前端需要三个部分
下拉框
- 设置属性name = “field”
- 下拉框内容根据数据库中的字段按查询需求进行设置
输入框
- 设置属性name = “keyword”
搜索按钮
- 这里使用input标签,设置type = “submit”
以上部分需要放在form表单中,用来提交数据到后端
<form action="/lessee/list" method="get">
<select name="field">
<option value="name">姓名</option>
<option value="idCard">身份证号</option>
</select>
<input type="text" name="keyword" placeholder="关键词">
<input class="btn btn-primary" type="submit" value="搜索">
</form>
3.1.2分页部分
预计效果
设置上一页,下一页和具体页的点击按钮,通过a标签实现。
要注意考虑第一页和最后一页的特殊情况。
在点击标签发送请求时,需要把查询关键字(keyword)和关键字字段(field)一起带到后台,方便数据库的查询操作。
<div>共有 ${total} 条记录,第 ${pageNo}/${pageCount} 页 </div>
<ul class="pagination">
<%-- 判断是不是第一页,如果不是,就显示上一页按钮 --%>
<c:if test="${pageNo != 1}">
<li class="paginate_button previous disabled }">
<%--发送请求时把关键字(keyword)和关键字字段(field)同时带到后台控制层--%>
<a href="/house/list?pageNo=${pageNo-1}&keyword=${keyword}&field=${field}">上一页</a>
</li>
</c:if>
<c:forEach var="i" begin="1" end="${pageCount}" step="1">
<%--这里通过三目运算判断此页码是不是当前浏览页,如果是,设置为选中样式--%>
<li class="paginate_button ${pageNo == i ? 'active' : ''}">
<a href="/house/list?pageNo=${i}&keyword=${keyword}&field=${field}">${i}</a>
</li>
</c:forEach>
<%-- 判断是不是最后一页,如果不是,就显示下一页按钮 --%>
<c:if test="${pageNo != pageCount}">
<li class="paginate_button next disabled">
<a href="/house/list?pageNo=${pageNo+1}&keyword=${keyword}&field=${field}">下一页</a>
</li>
</c:if>
</ul>
3.2后端实现
3.2.1 Servlet部分
接收前端请求和数据后,调用Service层根据输入框内容查询数据
@WebServlet("/house/list")
public class HouseListServlet extends HttpServlet {
private HouseService houseService = new HouseServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 构建map,用于存储参数
HashMap<String, Object> map = new HashMap<>();
// 每页展示数据行数
int pageSize = 5;
//----------- 模糊搜索 -----------
String keyword = req.getParameter("keyword"); // 前端搜索的关键字
String field = req.getParameter("field");// 搜索类型
map.put("keyword",keyword);
map.put("field",field);
// 将关键词和字段存入请求域,用于前端点击项发送请求时携带数据
req.setAttribute("keyword",keyword);
req.setAttribute("field",field);
//----------- 模糊搜索 -----------
//----------- 分页 -----------
String pageNoStr = req.getParameter("pageNo"); // 前端当前页面
// 如果没有获得当前页数,则默认从第一页开始
if (pageNoStr == null || "".equals(pageNoStr)) {
pageNoStr = "1";
}
int pageNo = Integer.parseInt(pageNoStr);
// 获得数据总条数
int total = houseService.count(map);
// 计算总页数
int pageCount = total % pageSize == 0 ? total / pageSize : total / pageSize + 1;
map.put("pageNo",pageNo);
map.put("pageSize",pageSize);
// 把数据带回前端界面
req.setAttribute("pageNo",pageNo);
req.setAttribute("pageCount",pageCount);
req.setAttribute("total",total);
//----------- 分页 -----------
// 根据查询条件获取数据列表
List<House> list = houseService.findAll(map);
// 如果查询结果不是空,则携带数据跳转到列表界面
if(list != null) {
req.setAttribute("list",list);
req.getRequestDispatcher("/view/house/list.jsp").forward(req,resp);
}
}
}
3.2 Service部分
Service层调用Dao层方法,进行JDBC操作
/**
* 查全部房屋信息
* @return
*/
@Override
public List<House> findAll(HashMap<String, Object> map) {
return houseDao.findAll(map);
}
3.3 Dao部分
Dao层实现findAll()方法,查询符合条件的全部数据,并存入集合中返回
/**
* 查全部房屋信息
* @return
*/
@Override
public List<House> findAll(HashMap<String, Object> map) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
House house = null;
ArrayList<House> list = new ArrayList<>( );
int pageNo = (int) map.get("pageNo");
int pageSize = (int) map.get("pageSize");
String field = (String)map.get("field");
String keyword = (String)map.get("keyword");
try{
conn = DBUtil.getConnection( );
// 基本查询语句
String baseSql = "select * from house where status = 1 ";
String searchSql = "";
// 判断关键字和字段是否为null或空字符串,如果为空直接查全部
if (field != null && !"".equals(field) && keyword != null && !"".equals(keyword)) {
// 判断关键字字段,根据字段拼接相应的查询语句
if ("address".equals(field)) {
searchSql = "and " + field +" like '%"+keyword+"%' ";
} else if ("floor".equals(field)) {
searchSql = "and " + field +" = " + keyword;
}
baseSql += searchSql;
}
// 限制每页数据的个数(限制查询)
baseSql += " limit ?,?";
ps = conn.prepareStatement(baseSql);
ps.setInt(1,(pageNo - 1) * pageSize);
ps.setInt(2,pageSize);
rs = ps.executeQuery( );
while (rs.next()) {
house = new House();
house.setId(rs.getInt("id"));
house.setAddress(rs.getString("address"));
house.setFloor(rs.getInt("floor"));
house.setRoomNum(rs.getInt("roomNum"));
house.setArea(rs.getString("area"));
house.setDir(rs.getString("dir"));
house.setDeco(rs.getInt("deco"));
house.setAir(rs.getInt("air"));
house.setPrice(rs.getDouble("price"));
house.setRentStatus(rs.getInt("rentStatus"));
house.setImage(rs.getString("image"));
house.setAddTime(rs.getDate("addtime"));
house.setUpdateTime(rs.getDate("updateTime"));
house.setStatus(rs.getInt("status"));
list.add(house);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
DBUtil.closeAll(conn,ps,rs);
}
// 返回结果集合
return list;
}
四、结果
以上就是模糊查询后的分页实现,加上其他增删改等功能和前端样式后,整体效果如下图
五、实现过程中的常见BUG
1.搜索后,再点下一页是全部数据的下一页不是模糊搜索的下一页
- 原因: 点击下一页或上一页时,后台没有接收到关键词keyword,所以Dao层就没有拼接where后sql语句
- 解决: 在点击下一页时,在路径中拼接上关键词(关键词就需要后台将关键词返回)
2.搜索后,左下角的数据总数和当前页等信息显示为0或其他错误的数字
原因1:前端界面没有从域中取值
解决:在相应位置从域中取出响应值,如 :共有
${total}
条记录,第${pageNo}/${pageCount}
页原因2:前端界面取了值,但Servlet跳转界面时没有向域中存入相应数据
解决:Servlet跳转界面前把值存入请求域,然后通过请求转发跳转界面(不能用重定向,因为重定向不能携带域跳转界面)
原因3:查询方法count()实现过程中sql语句书写错误,导致返回的total值错误
解决:检查sql语句,如有错误则改正