04月11日 晴 一切重来
度过留级小插曲,课程继续,今天讲高级查询,具体有2个块知识点:1>分页, 2>带条件查询,这里简单表述一下理解。
分页
概念:大量数据无法一下子全部显示, 可将数据等分,然后一页一页显示。效果如下
要呈现出分页效果需要几个要素:
页面传入:
1>当前页(currentPage) 2>每页显示条数(pageSize)
mysql中的分页语法: select * from 表 limit (currentPage-1) * pageSize, pageSize;
查询SQL
1>总记录数(totalCount)
select count(id) from 表
2>当前页列表数据(data)
select * from 表 limit (currentPage-1) * pageSize, pageSize;
计算出来
1>上一页 (prePage)
prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1;
2>下一页 (nextPage)
nextPage = currentPage + 1 <= this.totalPage ? currentPage + 1 : this.totalPage;
3>总页数 (totalPage)
totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
结合上面的分析,
表现层的Servlet定义QueryObject对象接收参数
/**
* 封装分页需要的两个条件数据
*/
@Getter
@Setter
public class QueryObject {
private int currentPage = 1;
private int pageSize = 3;
public int getBeginIndex(){
return (currentPage - 1) * pageSize;
}
}
使用PageResult封装页面分页显示数据
/**
* 用来封装结果数据
*/
@Getter
public class PageResult {
// 1 两个用户输入
private int currentPage; // 要查询的页码
private int pageSize; // 每页显示的最大记录数
// 2 两条SQL 的执行结果
private List data; // 当前页的数据
private int totalCount; // 总记录数
// 3 三个运算的值
private int totalPage; // 总页数
private int prevPage; // 上一页页码
private int nextPage; // 下一页的页码
/**
* 当表格中没有数据时使用的构造器
*/
public PageResult(int currentPage,int pageSize){
this(currentPage,pageSize,new ArrayList(),0);
}
public PageResult(int currentPage, int pageSize, List data, int totalCount) {
this.currentPage = currentPage;
this.pageSize = pageSize;
this.data = data;
this.totalCount = totalCount;
// 做3个运算
this.prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1;
this.totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
this.nextPage = currentPage + 1 <= this.totalPage ? currentPage + 1 : this.totalPage;
}
}
调用业务层实现分页逻辑
protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1 接收请求参数,封装成对象
QueryObject qo = new QueryObject();
// 两个分页的查询条件
String currentPage = req.getParameter("currentPage");
if (StringUtil.hasLength(currentPage)) {
qo.setCurrentPage(Integer.valueOf(currentPage));
}
String pageSize = req.getParameter("pageSize");
if (StringUtil.hasLength(pageSize)) {
qo.setPageSize(Integer.valueOf(pageSize));
}
// 2 调用业务方法来处理请求
PageResult result = service.query(qo);
// 存入到作用域对象中
req.setAttribute("result",result);
req.setAttribute("qo",qo);
// 3 控制跳转
req.getRequestDispatcher("/WEB-INF/views/product/list.jsp").forward(req,resp);
}
public PageResult query(QueryObject qo) {
// 获取两条SQL 的执行结果
// 1 查询满足条件的总记录数
int totalCount = dao.selectForCount(qo);
if (totalCount <= 0) {
return new PageResult(qo.getCurrentPage(),qo.getPageSize());
}
// 2 查询满足条件的结果集数据
List<具体对象> list = dao.selectForList(qo);
// 3 封装成对象返回给Servlet
return new PageResult(qo.getCurrentPage(),qo.getPageSize(),list,totalCount);
}
调用DAO层实现totalCount 跟 data数据查询
<select id="selectForList" resultType="具体对象">
SELECT * FROM 表
LIMIT #{beginIndex},#{pageSize}
</select>
<select id="selectForCount" resultType="int">
SELECT COUNT(*) FROM 表
</select>
带条件查询
在分页代码基础上进行条件过滤
页面:
假设页面传入关键字 keyword, 需要对keyword进行关键字查询。
原理:
select * from 表 where 条件列 like '%keyword%'’ limit (currentPage-1) * pageSize, pageSize;
观察发现, 也就多了where 条件, 此时只需要调整接收参数的QueryObject对象跟DAO的sql即可
/**
* 封装分页需要的两个条件数据
*/
@Getter
@Setter
public class QueryObject {
private int currentPage = 1;
private int pageSize = 3;
private String keyword; //查询条件
public int getBeginIndex(){
return (currentPage - 1) * pageSize;
}
}
<select id="selectForList" resultType="具体对象">
SELECT * FROM 表
WHERE 条件列 like concat('%',${keyword},'%')
LIMIT #{beginIndex},#{pageSize}
</select>
<select id="selectForCount" resultType="int">
SELECT COUNT(*) FROM 表
WHERE 条件列 like concat('%',${keyword},'%')
</select>
到这, 分页 + 条件查询 = 高级查询就完成了, 后续如果多条件,可以按照上面逻辑完善即可。