您好,登錄后才能下訂單哦!
今天小編給大家分享一下如何用Java實現(xiàn)分頁查詢功能的相關(guān)知識點,內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
分頁查詢將數(shù)據(jù)庫中龐大的數(shù)據(jù)分段顯示,每頁顯示用戶自定義的行數(shù),提高用戶體驗度,最主要的是如果一次性從服務(wù)器磁盤中讀出全部數(shù)據(jù)到內(nèi)存,有內(nèi)存溢出的風(fēng)險
假分頁: 其原理還是將所有的數(shù)據(jù)讀到內(nèi)存中,翻頁從內(nèi)存中讀取數(shù)據(jù), 優(yōu)點: 實現(xiàn)簡單,性能高 缺點:如果數(shù)據(jù)大容易造成內(nèi)存溢出
真分頁: 每次翻頁從數(shù)據(jù)庫查詢數(shù)據(jù)(即磁盤) , 優(yōu)點 : 不容易造成內(nèi)存溢出 缺點: 實現(xiàn)復(fù)雜,性能相對低一些
一般分頁的功能包括: 首頁 上一頁 下一頁 末頁 當(dāng)前是多少頁 總共多少頁 一共多少行數(shù)據(jù) 跳轉(zhuǎn)到第幾頁 每頁多少條數(shù)據(jù) 我們需要將這個數(shù)據(jù)查詢出來封裝到一個對象中,體現(xiàn)了封裝思想,也節(jié)省了很多復(fù)雜代碼
分頁需要傳遞的參數(shù)
需要用戶傳入的參數(shù):
currentPage: 當(dāng)前頁,跳轉(zhuǎn)到第幾頁, 第一次訪問,我們創(chuàng)建一個對象,默認(rèn)值是1
pageSize: 每頁顯示多少行數(shù)據(jù), 第一次我們也給個默認(rèn)值 比如10條
分頁需要展示的數(shù)據(jù)
1.當(dāng)前頁的貨品信息
2.首頁是第幾頁
3.上一頁是第幾頁
4.下一頁是第幾頁
5.一共有多少頁,和末頁的值是一樣的
6.數(shù)據(jù)一共有多少條(行)
7.當(dāng)前是第幾頁
8.每頁顯示多少條信息
分頁需要展示的數(shù)據(jù)的來源
來源于用戶上傳: 當(dāng)前頁 , 每頁顯示多少條數(shù)據(jù)
來源于數(shù)據(jù)庫查詢 : 數(shù)據(jù)總條數(shù) , 每一頁需要展示的商品信息
來源于根據(jù)上面的已知信息計算 : 總頁數(shù) , 上一頁 , 下一頁
書寫從數(shù)據(jù)庫查詢的sql語句
第一條sql 查詢數(shù)據(jù)庫中有多少條數(shù)據(jù),COUNT后面不能有空格
SELECT COUNT(*) FROM 表名
第二條sql 根據(jù)傳入的參數(shù)查詢第幾頁,一頁多少條數(shù)據(jù)的結(jié)果集
# 第一個 ?:從哪一個索引的數(shù)據(jù)開始查詢(默認(rèn)從 0 開始) # 第二個 ?:查詢多少條數(shù)據(jù) SELECT * FROM 表名 LIMIT ?, ?
接下來分析第二條 SQL 中兩個 ? 取值來源:
假設(shè) product 表中有 21 條數(shù)據(jù),每頁分 5 條數(shù)據(jù):
查詢第一頁數(shù)據(jù):SELECT * FROM product LIMIT 0, 5
查詢第二頁數(shù)據(jù):SELECT * FROM product LIMIT 5, 5
查詢第三頁數(shù)據(jù):SELECT * FROM product LIMIT 10, 5
查詢第四頁數(shù)據(jù):SELECT * FROM product LIMIT 15, 5
通過尋找規(guī)律發(fā)現(xiàn):第一個 ? 取值來源于 (currentPage - 1) * pageSize;第二個 ? 取值來源于
pageSize,即都來源于用戶傳遞的分頁參數(shù)。
總頁數(shù),上一頁和下一頁
// 優(yōu)先計算總頁數(shù) int totalPage = rows % pageSize == 0 ? rows / pageSize : rows / pageSize + 1; //上一頁等于當(dāng)前頁-1,但不能超過1頁界限 int prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1; //下一頁等于當(dāng)前頁+1,但不能超過總頁數(shù)界限 int nextPage = currentPage + 1 <= totalPage ? currentPage + 1 : totalPage;
分頁查詢實現(xiàn)
訪問流程:
封裝需要展示的數(shù)據(jù)
如果不封裝數(shù)據(jù),每個數(shù)據(jù)都需要存到作用域中,數(shù)據(jù)太分散,不方便統(tǒng)一管理
/** * 封裝結(jié)果數(shù)據(jù)(某一頁的數(shù)據(jù)) */ @Getter public class PageResult<T> { // 兩個用戶的輸入 private int currentPage; // 當(dāng)前頁碼 private int pageSize; // 每頁顯示的條數(shù) // 兩條 SQL 語句執(zhí)行的結(jié)果 private int totalCount; // 總條數(shù) private List<T> data; // 當(dāng)前頁結(jié)果集數(shù)據(jù) // 三個程序計算的數(shù)據(jù) private int prevPage; // 上一頁頁碼 private int nextPage; // 下一頁頁碼 private int totalPage; // 總頁數(shù)/末頁頁碼 // 分頁數(shù)據(jù)通過下面構(gòu)造期封裝好 public PageResult(int currentPage, int pageSize, int totalCount, List<T> data) { this.currentPage = currentPage; this.pageSize = pageSize; this.totalCount = totalCount; this.data = data; // 計算三個數(shù)據(jù) this.totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1; this.prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1; this.nextPage = currentPage + 1 <= this.totalPage ? currentPage + 1 : this.totalPage; } }
持久層DAO
Mybatis提供的操作方法只能傳入一個參數(shù)執(zhí)行SQL任務(wù),而我們現(xiàn)在查詢某一頁的數(shù)據(jù),需要知道是第幾頁和每頁多少條數(shù)據(jù)這兩個參數(shù),所以我們需要將這兩個參數(shù)封裝在一個對象里面
編寫一個類(起名叫查詢對象類)來封裝這些查詢數(shù)據(jù)
@Setter @Getter /** * 封裝分頁查詢需要的兩個請求傳入的分頁參數(shù) */ public class QueryObject { private int currentPage = 1; // 當(dāng)前頁碼,要跳轉(zhuǎn)到哪一頁的頁碼(需要給默認(rèn)值) private int pageSize = 3; // 每頁顯示條數(shù)(需要給默認(rèn)值) }
再書寫持久層DAO接口和實現(xiàn)類
//DAO接口提供兩個根據(jù)查詢對象的查詢方法 int queryForCount(); List<Product> queryForList(QueryObject qo); //DAO實現(xiàn)類 @Override //查詢數(shù)據(jù)庫總數(shù)據(jù)條數(shù) public int queryForCount() { SqlSession session = MyBatisUtil.getSession(); int totalCount = session.selectOne("cn.xxx.mapper.ProductMapper.queryForCount"); session.close(); return totalCount; } @Override //查詢某一頁的結(jié)果集 public List<Product> queryForList(QueryObject qo) { SqlSession session = MyBatisUtil.getSession(); List<Product> products = session.selectList("cn.xxx.mapper.ProductMapper.queryForList",qo); session.close(); return products; }
修改productMapper.xml
<select id="queryForCount" resultType="int"> SELECT COUNT(*) FROM product </select> <select id="queryForList" resultType="cn.xxx.domain.Product"> SELECT * FROM product LIMIT #{start}, #{pageSize} </select>
修改QueryObject.java
給這個類增加getStart方法,返回根據(jù)當(dāng)前頁,每頁大小需要從數(shù)據(jù)庫從第幾行開始顯示
@Setter @Getter /** * 封裝分頁查詢需要的兩個請求傳入的分頁參數(shù) */ public class QueryObject { private int currentPage = 1; // 當(dāng)前頁碼,要跳轉(zhuǎn)到哪一頁的頁碼(需要給默認(rèn)值) private int pageSize = 3; // 每頁顯示條數(shù)(需要給默認(rèn)值) // 用于 Limit 子句第一個 ? 取值 public int getStart(){ return (currentPage - 1) * pageSize; } }
業(yè)務(wù)層ProductService
調(diào)用持久層DAO完成數(shù)據(jù)的查詢,并將多個數(shù)據(jù)封裝到一個對象中
//IProductService接口 public interface IProductService { /** * 完成查詢某一頁的業(yè)務(wù)邏輯功能 */ PageResult<Product> query(QueryObject qo); } //Service實現(xiàn)類 public class ProductServiceImpl implements IProductService { private IProductDAO productDAO = new ProductDAOImpl(); @Override public PageResult<Product> query(QueryObject qo) { // 調(diào)用 DAO 查詢數(shù)據(jù)數(shù)量 int totalCount = productDAO.queryForCount(); // 為了性能加入判斷,若查詢的數(shù)據(jù)數(shù)量為 0,說明沒有數(shù)據(jù),返回返回空集合,即集合中沒有 元素 if(totalCount == 0){ return new PageResult(qo.getCurrentPage(), qo.getPageSize(), totalCount, Collections.emptyList()); } // 執(zhí)行到這里代表有數(shù)據(jù),查詢當(dāng)前頁的結(jié)果數(shù)據(jù) List<Product> products = productDAO.queryForList(qo); return new PageResult(qo.getCurrentPage(), qo.getPageSize(), totalCount, products); } }
前臺分頁功能實現(xiàn)
1.必須先完成業(yè)務(wù)層組件,保證后臺測試通過。
2.遵循 MVC 思想。
3.瀏覽器發(fā)出分頁請求參數(shù)(去往第幾頁/每頁多少條數(shù)據(jù)),在 Servlet 中接收這些參數(shù),并封裝
4.到 QueryObject 對象,調(diào)用 Service 中分頁查詢方法(query)。
5.把得到的分頁查詢結(jié)果對象(PageResult)共享在請求作用域中,跳轉(zhuǎn)到 JSP,顯示即可。
6.修改 JSP 頁面,編寫出分頁條信息(分頁條中的信息來源于 PageResult 對象)。
修改ProductServlet.java和展示jsp
1.獲取頁面請求參數(shù),判斷是查詢操作,調(diào)用查詢方法,獲取分頁參數(shù)
2.將參數(shù)封裝成查詢對象QueryObject
3.調(diào)用業(yè)務(wù)層方法查詢某一頁數(shù)據(jù)
4.將查詢出來的結(jié)果存到作用域中
5.轉(zhuǎn)發(fā)到展示頁面jsp
6.在jsp從作用域中將結(jié)果取出來響應(yīng)到瀏覽器
//創(chuàng)建業(yè)務(wù)層對象 private IProductService productService = new ProductServiceImpl(); protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { QueryObject qo = new QueryObject(); // 獲取請求參數(shù) currentPage,并轉(zhuǎn)型封裝 String currentPage = req.getParameter("currentPage"); if(StringUtil.hasLength(currentPage)) { qo.setCurrentPage(Integer.valueOf(currentPage)); } // 獲取請求參數(shù) pageSize,并轉(zhuǎn)型封裝 String pageSize = req.getParameter("pageSize"); if(StringUtil.hasLength(pageSize)) { qo.setPageSize(Integer.valueOf(pageSize)); } // 調(diào)用業(yè)務(wù)層方法來處理請求查詢某一頁數(shù)據(jù) PageResult<Product> pageResult = productService.query(qo); // 把數(shù)據(jù)共享給 list.jsp req.setAttribute("pageResult", pageResult); // 控制跳轉(zhuǎn)到 list.jsp 頁面 req.getRequestDispatcher("/WEB-INF/views/product/list.jsp").forward(req, resp); }
修改jsp文件,使用JSTL+EL獲取作用域中的數(shù)據(jù)
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>產(chǎn)品列表</title> <script type="text/javascript"> window.onload = function () { var trClzs = document.getElementsByClassName("trClassName"); for(var i = 0; i < trClzs.length; i++){ trClzs[i].onmouseover = function () { console.log(1); this.style.backgroundColor = "gray"; } trClzs[i].onmouseout = function () { console.log(2); this.style.backgroundColor = ""; } } } // 分頁 JS function changePageSize() { document.forms[0].submit(); } </script> </head> <body> <a href="/replaceImg.jsp" rel="external nofollow" ><img src="${USER_IN_SESSION.headImg}" title="更換頭 像"/></a><br/> <a href="/product?cmd=input" rel="external nofollow" >添加</a> <form action="/product"> <table border="1" cellspacing="0" cellpadding="0" width="80%"> <tr> <th>編號</th> <th>貨品名</th> <th>分類編號</th> <th>零售價</th> <th>供應(yīng)商</th> <th>品牌</th> <th>折扣</th> <th>進(jìn)貨價</th> <th>操作</th> </tr> <c:forEach var="product" items="${pageResult.data}" varStatus="status"> <tr class="trClassName"> <td>${status.count}</td> <td>${product.productName}</td> <td>${product.dir_id}</td> <td>${product.salePrice}</td> <td>${product.supplier}</td> <td>${product.brand}</td> <td>${product.cutoff}</td> <td>${product.costPrice}</td> <td> <a href="/product?cmd=delete&id=${product.id}" rel="external nofollow" >刪除</a> <a href="/product?cmd=input&id=${product.id}" rel="external nofollow" >修改</a> </td> </tr> </c:forEach> <tr align="center"> <td colspan="9"> <a href="/product?currentPage=1" rel="external nofollow" >首頁</a> <a href="/product?currentPage=${pageResult.prevPage}" rel="external nofollow" >上一頁</a> <a href="/product?currentPage=${pageResult.nextPage}" rel="external nofollow" >下一頁</a> <a href="/product?currentPage=${pageResult.totalPage}" rel="external nofollow" >尾頁</a> 當(dāng)前第 ${pageResult.currentPage} / ${pageResult.totalPage} 頁 一共 ${pageResult.totalCount} 條數(shù)據(jù) 跳轉(zhuǎn)到<input type="number" onchange="changePageSize()" name="currentPage" value="${pageResult.currentPage}" 頁 每頁顯示 <select name="pageSize" onchange="changePageSize()"> <option value="3" ${pageResult.pageSize == 3 ? 'selected' : ''}> 3 </option> <option value="5" ${pageResult.pageSize == 5 ? 'selected' : ''}> 5 </option> <option value="8" ${pageResult.pageSize == 8 ? 'selected' : ''}> 8 </option> </select>條數(shù)據(jù) </td> </tr> </table> </form> </body> </html>
常見問題
若開始翻頁操作成功,翻了幾頁不能翻了,只能重啟tomcat才能翻,問題: DAO中沒有關(guān)閉SqlSession對象
以上就是“如何用Java實現(xiàn)分頁查詢功能”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。