分頁和過濾查詢
流程圖 :

1 設(shè)計(jì)和原理分析

前面我們已經(jīng)講過分頁查詢了 , 接下來我們講講 過濾查詢 .
思路 : 從后臺開始寫 , 寫好測試 , 測試成功 ; 開始寫前臺 .
這里我們需要 MyBatis動態(tài)sql語句
為了解決在 xml 中拼接 SQL 的問題,此處需要來學(xué)習(xí) MyBatis 的動態(tài) SQL
<where> 和<if> 標(biāo)簽的配合使用
<select id="queryCount" resultType="int">
SELECT count(*) FROM t_armoire
<where>
<if test="keyword!=null and keyword!=''">
AND supplier LIKE concat('%',#{keyword},'%')
</if>
<if test="minPrice!=null">
AND price >= #{minPrice}
</if>
<if test="maxPrice!=null">
AND price <= #{maxPrice}
</if>
</where>
</select>
<select id="queryResult" resultType="armoire">
SELECT * FROM t_armoire
<where>
<if test="keyword!=null and keyword!=''">
AND supplier LIKE concat('%',#{keyword},'%')
</if>
<if test="minPrice!=null">
AND price >= #{minPrice}
</if>
<if test="maxPrice!=null">
AND price <= #{maxPrice}
</if>
</where>
limit #{beginIndex},#{pageSize}
</select>
首先 , 我們現(xiàn)在需要用戶傳入的 過濾條件封裝成對象 ArmoireQueryObject, 去繼承 QueryObject ,這樣我們通過 ArmoireQueryObject就可以獲取用戶傳來的所有參數(shù) .
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class ArmoireQueryObject extends QueryObject {
//用戶傳來 高級查詢 的參數(shù)
//1. 關(guān)鍵字 2. 最小值 3. 最大值
private String keyword;
private Integer minPrice;
private Integer maxPrice;
//繼承 這樣 其實(shí)已經(jīng)有 5+2 + getBegin 數(shù)據(jù)了
}
list.jsp 操作步驟 添加在 form標(biāo)簽中
<p align="center"> //這里是value 是回顯,可以先不管
關(guān)鍵字:<input type="text" name="keyword" value="${aq.keyword}">
價(jià)格:<input type="number" name="minPrice" value="${aq.minPrice}"> ~ <input type="number" name="maxPrice" value="${aq.maxPrice}">
<input type="submit" value="提交"></p>
注意:一般的,為了避免不必要的麻煩,讓字段名稱和表單中的請求參數(shù)名稱相同 .
DAO
public interface IArmoireDAO {
//高級查詢 總條數(shù)
int queryCount(ArmoireQueryObject aq);
//高級查詢 頁面結(jié)果集
List<?>queryResult(ArmoireQueryObject aq);
}
public class ArmoireDAOImpl implements IArmoireDAO {
@Override
public int queryCount(ArmoireQueryObject aq) {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
int count = sqlSession.selectOne("cn.wolfcode.amis.mapper.ArmoireMapper.queryCount", aq);
sqlSession.close();
return count;
}
@Override
public List<?> queryResult(ArmoireQueryObject aq) {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
List<?>list = sqlSession.selectList("cn.wolfcode.amis.mapper.ArmoireMapper.queryResult", aq);
sqlSession.close();
return list;
}
}
注意 ; MyBatisUtil 自己去拿 . 算了 還是寫給你吧 (這是我封裝好的工具類 , 拿去用吧 害 !)
public class MyBatisUtil {
private MyBatisUtil() {
//私有化構(gòu)造器
}
static SqlSessionFactory factory = null;
static {
try {
factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
return factory.openSession();
}
}
還有后面 service要用的工具類 , 方便點(diǎn) , 統(tǒng)統(tǒng)給你. StringUtil
public class StringUtil {
private StringUtil(){
//私有化構(gòu)造器
}
//判空
public static boolean hasLength(String str){
return str!=null && !"".equals(str.trim());
}
}
后臺這樣其實(shí)就已經(jīng)寫好了 , 測試下吧 . 成功繼續(xù)...
想想我們 需要給前臺 返回什么數(shù)據(jù) ??? 之前分頁查詢已經(jīng)說過了 .
兩輸 , 兩查 , 三計(jì)算 封裝成對象 .
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class PageResult {
//存 2輸 2查 3計(jì)算
private int currentPage;
private int pageSize;
//2查
private int totalCount;
private List<?> listResult;
//3 計(jì)算 上一頁 下一頁 總頁數(shù)
private int totalPage;
private int prevPage;
private int nextPage;
//自定義構(gòu)造器
public PageResult(int currentPage,int pageSize,int totalCount,List<?> listResult){
this.currentPage=currentPage;
this.pageSize=pageSize;
this.totalCount=totalCount;
this.listResult=listResult;
this.totalPage=totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1;
this.prevPage=currentPage>1?currentPage-1:1;
this.nextPage=currentPage<totalPage?currentPage+1:totalPage;
}
}
我們看看service 層 (調(diào)用方法: 參數(shù): 前臺的數(shù)據(jù)傳來封裝到 ArmoireQueryObject 對象中)返回一個前臺需要的 所有數(shù)據(jù) PageResult對象過去 .
public interface IArmoireService {
//業(yè)務(wù)層
PageResult query(ArmoireQueryObject aq);
}
簡單吧 ! ! !
有了接口 , 就要去實(shí)現(xiàn)吧 , 不然要它何用 ?
實(shí)現(xiàn) :
public class ArmoireServiceImpl implements IArmoireService {
@Override
public PageResult query(ArmoireQueryObject aq) {
IArmoireDAO dao=new ArmoireDAOImpl();
List<?> list = dao.queryResult(aq);
int count = dao.queryCount(aq);
if(count==0){
//如果為0 , 返回空集
return new PageResult(aq.getCurrentPage(),aq.getPageSize(),0,new ArrayList<>());
}
return new PageResult(aq.getCurrentPage(),aq.getPageSize(),count,list);
}
}
真棒 , 都看到這里了 , 那我們是不是應(yīng)該做啥事呢 ? 肯定是測試呀 !(還用想嗎, 一天天的啥也不是啊哈! ! !)
測試成功 ...
我們開始寫 servlet吧 快結(jié)束了 .
@WebServlet("/arm")
public class ArmoireServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
IArmoireService service=new ArmoireServiceImpl();
ArmoireQueryObject aq = new ArmoireQueryObject();
//分頁查詢 : 用戶輸入
String strCurrentPage = req.getParameter("currentPage");
if(StringUtil.hasLength(strCurrentPage)){
Integer currentPage = Integer.valueOf(strCurrentPage);
aq.setCurrentPage(currentPage);
}
String strPageSize = req.getParameter("pageSize");
if(StringUtil.hasLength(strPageSize)){
Integer pageSize = Integer.valueOf(strPageSize);
aq.setPageSize(pageSize);
}
//過濾查詢
String keyword = req.getParameter("keyword");
aq.setKeyword(keyword);
String strMinPrice = req.getParameter("minPrice");
if(StringUtil.hasLength(strMinPrice)){
Integer minPrice = Integer.valueOf(strMinPrice);
aq.setMinPrice(minPrice);
}
String strMaxPrice = req.getParameter("maxPrice");
if(StringUtil.hasLength(strMaxPrice)){
Integer maxPrice = Integer.valueOf(strMaxPrice);
aq.setMaxPrice(maxPrice);
}
PageResult list = service.query(aq);
//共享
req.setAttribute("aq",aq);//回顯數(shù)據(jù) 這里有 關(guān)鍵字 最大 最小 +2
req.setAttribute("list",list);//返回 頁面需要的 結(jié)果數(shù)據(jù)
//跳轉(zhuǎn)
req.getRequestDispatcher("/list.jsp").forward(req,resp);
}
}
總算寫好了 , 那我們要干啥啊 , 問我 ? ? ? 把它裝上 jsp頁面上 .
看著有點(diǎn)復(fù)雜 , 其實(shí)靜下心來 , 看看 , 其實(shí) JAVA 也就那樣 . 其實(shí) 學(xué)習(xí) JAVA 也是一種修行哈 , 越努力越幸運(yùn) , 加油 !
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>信息管理系統(tǒng)</title>
<script>
function onChange() {
document.forms[0].submit();
}
function goPage(pageNum) {
document.getElementById("currentPageId").value = pageNum;
document.forms[0].submit();
}
</script>
</head>
<body>
<h3 align="center">貨品信息查詢系統(tǒng)</h3>
<form action="/arm">
<p align="center">
關(guān)鍵字:<input type="text" name="keyword" value="${aq.keyword}">
價(jià)格:<input type="number" name="minPrice" value="${aq.minPrice}"> ~ <input type="number" name="maxPrice" value="${aq.maxPrice}">
<input type="submit" value="提交"></p>
<table border="1" cellpadding="0" cellspacing="0" style="width: 80%" align="center">
<tr>
<th>序號</th>
<th>出產(chǎn)商</th>
<th>類型</th>
<th>價(jià)格</th>
</tr>
<c:forEach items="${list.listResult}" var="arm" varStatus="vs">
<tr>
<td>${vs.count}</td>
<td>${arm.supplier}</td>
<td>${arm.type}</td>
<td>${arm.price}</td>
</tr>
</c:forEach>
<tr align="center">
<td colspan="4">
<a href="#" onclick="goPage(1)">首頁</a>
<a href="#" onclick="goPage(${list.prevPage})">上一頁</a>
<a href="#" onclick="goPage(${list.nextPage})">下一頁</a>
<a href="#" onclick="goPage(${list.totalPage})">末頁</a>
當(dāng)前${list.currentPage}頁
共${list.totalPage}頁
跳轉(zhuǎn)<input type="number" name="currentPage" onchange="onChange()" style="width: 60px"
value="${list.currentPage}" id="currentPageId">頁
每頁顯示
<select name="pageSize">
<option value="3" ${list.pageSize==3?'selected':''}> 3</option>
<option value="5" ${list.pageSize==5?'selected':''}> 5</option>
<option value="8" ${list.pageSize==8?'selected':''}> 8</option>
</select>
條數(shù)據(jù)
</td>
</tr>
</table>
</form>
</body>
</html>