La requête de page affiche les énormes données de la base de données en segments. Chaque page affiche un nombre de lignes défini par l'utilisateur pour améliorer l'expérience utilisateur. La chose la plus importante est que toutes les données soient lues à partir du disque du serveur. la mémoire en même temps, Il y a un risque de débordement de mémoire
Fausse pagination : Le principe est de lire toutes les données dans la mémoire et de tourner la page pour lire les données de la mémoire. Avantages : Simple. mise en œuvre, hautes performances Inconvénients : si les données sont volumineuses, il est facile de provoquer un débordement de mémoire. Véritable pagination : interrogez les données de la base de données (c'est-à-dire le disque) à chaque fois que la page est tournée. Avantages : Pas facile de provoquer un débordement de mémoire. Inconvénients : complexe. mise en œuvre, performances relativement faibles
Paramètres qui doivent être transmis. pour la pagination
Paramètres qui doivent être transmis par l'utilisateur :currentPage : page actuelle, à quelle page accéder, lors de la première visite, nous créons un objet, la valeur par défaut est 1
pageSize : combien de lignes de données sont affichés sur chaque page. Pour la première fois, nous donnerons également une valeur par défaut, telle que 10.
Les données qui doivent être affichées en pagination
1. Quelle page est la page d'accueil3. Quelle page est la page précédente ? 4. Quelle page est la page suivante ? 5. Combien de pages y a-t-il au total ? La valeur est la même que la dernière page. lignes) de données y a-t-il ? 7. La page actuelle est Quelle page
8. Combien d'informations sont affichées sur chaque page
La source des données qui doivent être affichées dans la pagination
provient du téléchargement de l'utilisateur. : page actuelle, combien de données sont affichées sur chaque page
sont calculées sur la base des informations connues ci-dessus : nombre total de pages , page précédente, page suivante
Écrivez l'instruction SQL interrogée à partir de la base de données
La première requête SQL dans la base de données Combien de données y a-t-il Il ne peut y avoir d'espaces après COUNT
SELECT COUNT(*) FROM 表名
La deuxième requête SQL ? page en fonction des paramètres transmis et de l'ensemble de résultats du nombre d'éléments de données sur une page# 第一个 ?:从哪一个索引的数据开始查询(默认从 0 开始)
# 第二个 ?:查询多少条数据
SELECT * FROM 表名 LIMIT ?, ?
Interrogez la première page de données : SELECT * FROM product LIMIT 0, 5
Interrogez la deuxième page de données : SELECT * FROM product LIMIT 5, 5Interrogez les données sur le troisième page : SELECT * FROM product LIMIT 10, 5
Interrogez les données sur la quatrième page : SELECT * FROM product LIMIT 15, 5Découvrez en recherchant le modèle : La première valeur provient de (currentPage - 1) * pageSize ; la deuxième valeur ? vient de
pageSize, c'est-à-dire qu'elles proviennent toutes des paramètres de pagination transmis par l'utilisateur.
Nombre total de pages, page précédente et page suivante
// 优先计算总页数 int totalPage = rows % pageSize == 0 ? rows / pageSize : rows / pageSize + 1; //上一页等于当前页-1,但不能超过1页界限 int prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1; //下一页等于当前页+1,但不能超过总页数界限 int nextPage = currentPage + 1 <= totalPage ? currentPage + 1 : totalPage;
Processus d'accès :
Encapsuler les données qui doivent être affichées
Si les données ne sont pas encapsulées , chaque donnée doit toutes être stockée dans le scope. Les données sont trop dispersées et peu pratiques pour une gestion unifiée
/** * 封装结果数据(某一页的数据) */ @Getter public class PageResult<T> { // 两个用户的输入 private int currentPage; // 当前页码 private int pageSize; // 每页显示的条数 // 两条 SQL 语句执行的结果 private int totalCount; // 总条数 private List<T> data; // 当前页结果集数据 // 三个程序计算的数据 private int prevPage; // 上一页页码 private int nextPage; // 下一页页码 private int totalPage; // 总页数/末页页码 // 分页数据通过下面构造期封装好 public PageResult(int currentPage, int pageSize, int totalCount, List<T> data) { this.currentPage = currentPage; this.pageSize = pageSize; this.totalCount = totalCount; this.data = data; // 计算三个数据 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; } }
Couche de persistance DAO
La méthode de fonctionnement fournie par Mybatis ne peut transmettre qu'un seul paramètre pour exécuter la tâche SQL, et nous interrogeons maintenant les données d'une certaine page, nous devons connaître les deux paramètres de quelle page il s'agit et combien de données par page, nous devons donc encapsuler ces deux paramètres dans un objet
Écrivez une classe (nommée classe d'objet de requête) pour encapsuler ces données de requête@Setter @Getter /** * 封装分页查询需要的两个请求传入的分页参数 */ public class QueryObject { private int currentPage = 1; // 当前页码,要跳转到哪一页的页码(需要给默认值) private int pageSize = 3; // 每页显示条数(需要给默认值) }
//DAO接口提供两个根据查询对象的查询方法 int queryForCount(); List<Product> queryForList(QueryObject qo); //DAO实现类 @Override //查询数据库总数据条数 public int queryForCount() { SqlSession session = MyBatisUtil.getSession(); int totalCount = session.selectOne("cn.xxx.mapper.ProductMapper.queryForCount"); session.close(); return totalCount; } @Override //查询某一页的结果集 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; }
<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>
Ajoutez la méthode getStart à cette classe et renvoyez la ligne à partir de laquelle la taille de chaque page doit être affichée à partir de la base de données en fonction de la page actuelle
@Setter @Getter /** * 封装分页查询需要的两个请求传入的分页参数 */ public class QueryObject { private int currentPage = 1; // 当前页码,要跳转到哪一页的页码(需要给默认值) private int pageSize = 3; // 每页显示条数(需要给默认值) // 用于 Limit 子句第一个 ? 取值 public int getStart(){ return (currentPage - 1) * pageSize; } }
Appelez la couche de persistance DAO pour terminer la requête de données et encapsuler plusieurs données dans un seul objet
//IProductService接口 public interface IProductService { /** * 完成查询某一页的业务逻辑功能 */ PageResult<Product> query(QueryObject qo); } //Service实现类 public class ProductServiceImpl implements IProductService { private IProductDAO productDAO = new ProductDAOImpl(); @Override public PageResult<Product> query(QueryObject qo) { // 调用 DAO 查询数据数量 int totalCount = productDAO.queryForCount(); // 为了性能加入判断,若查询的数据数量为 0,说明没有数据,返回返回空集合,即集合中没有 元素 if(totalCount == 0){ return new PageResult(qo.getCurrentPage(), qo.getPageSize(), totalCount, Collections.emptyList()); } // 执行到这里代表有数据,查询当前页的结果数据 List<Product> products = productDAO.queryForList(qo); return new PageResult(qo.getCurrentPage(), qo.getPageSize(), totalCount, products); } }
Implémentation de la fonction de pagination frontale
1. Les composants de la couche métier doivent être complétés en premier pour garantir la réussite du test backend.
2. Suivez la réflexion MVC.3. Le navigateur envoie les paramètres de requête de pagination (à quelle page accéder/combien de données par page), reçoit ces paramètres dans le servlet et les encapsule 4 Accédez à l'objet QueryObject et appelez la méthode de requête de pagination. (requête) dans le Service. 5. Partagez l'objet de résultat de requête de pagination obtenu (PageResult) dans la portée de la requête, accédez à JSP et affichez-le.
6. Modifiez la page JSP et écrivez les informations de la barre de pagination (les informations dans la barre de pagination proviennent de l'objet PageResult).
Modifiez ProductServlet.java et affichez jsp
1. Obtenez les paramètres de requête de page, déterminez qu'il s'agit d'une opération de requête, appelez la méthode de requête et obtenez les paramètres de pagination
. 3. Appelez la méthode de la couche métier pour interroger une certaine page de données4. Stockez les résultats de la requête dans la portée5. Transférez vers la page d'affichage jsp
6. Retirez les résultats de la portée dans jsp et répondez au navigateur.//创建业务层对象 private IProductService productService = new ProductServiceImpl(); protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { QueryObject qo = new QueryObject(); // 获取请求参数 currentPage,并转型封装 String currentPage = req.getParameter("currentPage"); if(StringUtil.hasLength(currentPage)) { qo.setCurrentPage(Integer.valueOf(currentPage)); } // 获取请求参数 pageSize,并转型封装 String pageSize = req.getParameter("pageSize"); if(StringUtil.hasLength(pageSize)) { qo.setPageSize(Integer.valueOf(pageSize)); } // 调用业务层方法来处理请求查询某一页数据 PageResult<Product> pageResult = productService.query(qo); // 把数据共享给 list.jsp req.setAttribute("pageResult", pageResult); // 控制跳转到 list.jsp 页面 req.getRequestDispatcher("/WEB-INF/views/product/list.jsp").forward(req, resp); }
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>产品列表</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>供应商</th> <th>品牌</th> <th>折扣</th> <th>进货价</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> 当前第 ${pageResult.currentPage} / ${pageResult.totalPage} 页 一共 ${pageResult.totalCount} 条数据 跳转到<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>条数据 </td> </tr> </table> </form> </body> </html>
Si l'opération de tournage de page réussit et que vous ne pouvez pas tourner après quelques pages, vous ne pouvez tourner Tomcat qu'en redémarrant Problème : L'objet SqlSession n'est pas fermé dans DAO
.Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!