SSM虾米音乐项目2--分页查询
1.分页查询的底层逻辑
- 首先根据用户输入的流派,进行模糊查询
- 根据查询的数据进行分页
- 需要前端用户提供pageNo(当前页数)和pageSize(每页的数据量)
- 并且要从后端计算count(总数据量)和totalPage(总页数),以及startNum(每页开始的记录)
- 从而将对应的页面数据展示给用户
2.分页查询的实现
分页查询所需要的所有属性
1.pageNo 当前页码 要查看的页码 前端用户决定
2.pageSize 当前每页的展示数量 前端用户决定或者后台设定好
3.startNum 开始行号 (pageNo-1)*pageSize sql语句做分页要查询的条件,通过计算得出
4.totalNum 所有页数 count/pageSize 通过计算得出
5.List 查询出的数据
6.totalCount 所有数据量 count(*) 通过查询数据库得出
分页查询的代码实现
首先创建分页的对象Page 为泛型类,因为每一个部分都需要实现分页,传递给前端,进行解读
page实体类
package com.qcby.utils;import java.util.List;/*** 封装前端需要的承载数据以及分页相关的一个实体* 自定义页的类*/
public class Page<T> {/*** 每页记录数(已知)*/private Integer pageSize = 5;/*** 页码(已知)*/private Integer pageNo = 1;/*** 指定查询条件下的总记录数(已知)*/private Integer totalCount = 0;/*** 指定查询条件下 的总页数*/private Integer totalPage = 1;/*** 使用sql查询的时候的开始行号*/private Integer startNum = 0;/*** 数据结果集*/private List<T> list;public Integer getPageSize() {return pageSize;}public void setPageSize(Integer pageSize) {this.pageSize = pageSize;}public Integer getPageNo() {return pageNo;}public void setPageNo(Integer pageNo) {this.pageNo = pageNo;}public Integer getTotalCount() {return totalCount;}public void setTotalCount(Integer totalCount) {this.totalCount = totalCount;}public Integer getTotalPage() {totalPage = totalCount/pageSize;if(totalCount == 0 || totalCount%pageSize != 0){//如果不能整除的话,需要取整+1totalPage++;}return totalPage;}public void setTotalPage(Integer totalPage) {this.totalPage = totalPage;}public Integer getStartNum() {return (pageNo -1 )*pageSize;}public void setStartNum(Integer startNum) {this.startNum = startNum;}public List<T> getList() {return list;}public void setList(List<T> list) {this.list = list;}
}
需要将page对象传递给前端,实现对应的页面渲染
mtype实体类
package com.qcby.model;import java.io.Serializable;public class Mtype implements Serializable {private Integer tid;private String tname;private String tdesc;public Mtype() {}public Mtype(Integer tid, String tname, String tdesc) {this.tid = tid;this.tname = tname;this.tdesc = tdesc;}public Integer getTid() {return tid;}public void setTid(Integer tid) {this.tid = tid;}public String getTname() {return tname;}public void setTname(String tname) {this.tname = tname == null ? null : tname.trim();}public String getTdesc() {return tdesc;}public void setTdesc(String tdesc) {this.tdesc = tdesc == null ? null : tdesc.trim();}@Overridepublic String toString() {return "Mtype{" +"tid=" + tid +", tname='" + tname + '\'' +", tdesc='" + tdesc + '\'' +'}';}
}
需要创建mtypeQuery实体类,将前端的页面数据pageNo等的数据,传递给后端进行数据查询,
mtypeQuery实体类
package com.qcby.query;import com.qcby.model.Mtype;/**封装query对象的目的是接受前端的请求参数,在后端处理业务逻辑,*知道用户的分页条件和查询条件* 只作为表现层接收前端参数封装使用*/
public class MtypeQuery extends Mtype{private Integer pageNo;private Integer startNum;private Integer pageSize=5;public Integer getPageSize() {return pageSize;}public void setPageSize(Integer pageSize) {this.pageSize = pageSize;}public Integer getPageNo() {return pageNo;}public void setPageNo(Integer pageNo) {this.pageNo = pageNo;}public Integer getStartNum() {return startNum;}public void setStartNum(Integer startNum) {this.startNum = startNum;}}
为什么mtype实体类当中没有设置有关页面的数据
因为在用page对象对mtype进行封装的时候,页面数据并没有用到前端的数据展示当中,而前端需要向后台服务器传递页面数据,因此需要再创建一个mtypeQuery实体类进行页面数据的封装
表现层
package com.qcby.controller;import com.qcby.model.Mtype;
import com.qcby.utils.Page;
import com.qcby.query.MtypeQuery;
import com.qcby.service.MtypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;/*** 流派业务的表现层* 处理前端页面的请求*/
@Controller
@RequestMapping("/mtype")
public class MtypeController {@Autowiredprivate MtypeService mtypeService;/*** 流派的分页条件查询接口* @param mq* @param model* @return*///展示流派信息@RequestMapping("/list")public String listType(MtypeQuery mq, Model model){if(mq.getPageNo() == null||mq.getPageNo()<=0){mq.setPageNo(1);}Page<Mtype> page = mtypeService.selectObjectByCondition(mq);//把Page对象传递给前端,进行解析呈现数据model.addAttribute("page", page);model.addAttribute("mq",mq);return "mtype";}}
通过model将用户查询到的page传递到前端进行页面渲染
前端用户通过mq将查询条件和分页条件 传递到后端
根据用户的查询条件进行分页的方法selectObjectByCondition需要创建在父接口BaseDao当中,再由浮层的实现类BaseServiceImpl实现,因为所有的类都需要实现该分页操作
BaseDao
package com.qcby.dao;import java.util.List;public interface BaseDao<Q, T> {/*** 保存数据* @param t*/public void insert(T t);/*** 根据主键查询对象* @param id* @return*/public T selectByPrimaryKey(Integer id);/*** 根据主键删除数据* @param id*/public void deleteByPrimaryKey(Integer id);/*** 修改数据* @param*/public void updateByPrimaryKeySelective(T t);/*** 查询所有的记录* @return*/public List<T> selectObjectAll();/*** 根据查询条件来查询数据* @param q* @return*/public List<T> selectObjectByCondition(Q q);/*** 根据查询条件来查询符合条件的记录数* @param q* @return*/public Integer selectObjectByConditionCount(Q q);
}
BaseService
package com.qcby.service;import com.qcby.utils.Page;import java.util.List;public interface BaseService<Q, T> {/*** 保存数据* @param t*/public void insert(T t);/*** 根据主键查询对象* @param id* @return*/public T selectByPrimaryKey(Integer id);/*** 根据主键删除数据* @param id*/public void deleteByPrimaryKey(Integer id);/*** 修改数据* @param*/public void updateByPrimaryKeySelective(T t);/*** 查询所有的记录* @return*/public List<T> selectObjectAll();/*** 分页查询* @param q* @return*/public Page<T> selectObjectByCondition(Q q);
}
BaseServiceImpl实现方法 分页的主要逻辑实现
package com.qcby.service.impl;import com.qcby.dao.BaseDao;
import com.qcby.utils.Page;
import com.qcby.service.BaseService;import java.lang.reflect.Method;
import java.util.List;public class BaseServiceImpl<Q,T> implements BaseService<Q,T> {/*** 可以支持两次注入,但是不好* 选择java基础的权限修饰符,以及set方法注入的形式改成一次注入*/protected BaseDao<Q, T> baseDao;@Overridepublic void insert(T t) {baseDao.insert(t);}@Overridepublic T selectByPrimaryKey(Integer id) {return baseDao.selectByPrimaryKey(id);}@Overridepublic void deleteByPrimaryKey(Integer id) {baseDao.deleteByPrimaryKey(id);}@Overridepublic void updateByPrimaryKeySelective(T t) {baseDao.updateByPrimaryKeySelective(t);}@Overridepublic List<T> selectObjectAll() {return baseDao.selectObjectAll();}//想办法给要返回的page对象所有属性赋值的过程@Overridepublic Page<T> selectObjectByCondition(Q q) {//获得查询对象的类对象//反射Class<? extends Object> qclass = q.getClass();Page<T> page = new Page<T>();try {//获得getPageNo对象Method method = qclass.getMethod("getPageNo", null);//反射调用getPageNo方法Integer pageNo = (Integer) method.invoke(q, null);//创建page对象,给返回去的page设置值page.setPageNo(pageNo);//计算开始行号和结束行号Integer startNum = page.getStartNum();System.out.println(startNum);//好的查询对象 的设置开始行号和结束行号的方法Method setStartNumMethod = qclass.getMethod("setStartNum", new Class[]{Integer.class});setStartNumMethod.invoke(q, startNum);} catch (Exception e) {e.printStackTrace();}//查询结果集List<T> list = baseDao.selectObjectByCondition(q);//查询指定查询条件下的总记录数Integer count = baseDao.selectObjectByConditionCount(q);//把总记录数设置给page对象page.setTotalCount(count);page.setList(list);return page;}
}
为什么要通过使用反射
通过反射获取类的类对象,可以知道当前的类到底对应的具体分页对象是谁。根据传递的q,通过反射调用方法拿到具体的每一个对象的getPageNo和getPageSize,设置给要返回到前端的page对象
MtypeMapper
package com.qcby.dao;import com.qcby.model.Mtype;
import com.qcby.query.MtypeQuery;public interface MtypeMapper extends BaseDao<MtypeQuery,Mtype>{}
MtypeService
package com.qcby.service;import com.qcby.model.Mtype;
import com.qcby.query.MtypeQuery;
import com.qcby.query.MtypeQuery;public interface MtypeService extends BaseService<MtypeQuery,Mtype>{}
MtypeServiceImpl
package com.qcby.service.impl;import com.qcby.query.MtypeQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import com.qcby.dao.MtypeMapper;
import com.qcby.model.Mtype;
import com.qcby.query.MtypeQuery;
import com.qcby.service.MtypeService;
@Service
public class MtypeServiceImpl extends BaseServiceImpl<MtypeQuery,Mtype> implements MtypeService {private MtypeMapper mtypeMapper;@Autowiredpublic void setMtypeMapper(MtypeMapper mtypeMapper) {this.mtypeMapper = mtypeMapper;this.baseDao=mtypeMapper;}}
前端页面
数据展示前端
<div class="body"><table class="table table-striped table-images"style="color: white;font-size: 14px"><thead><tr><th class="hidden-xs-portrait">序号</th><th class="hidden-xs">流派</th><th class="hidden-xs">描述</th><th></th></tr></thead><tbody><c:forEach items="${page.list}" var="mtype" varStatus="status"><tr><td class="hidden-xs-portrait">${mtype.tid}</td><td class="hidden-xs-portrait">${mtype.tname}</td><td class="hidden-xs"> ${mtype.tdesc} </td><td><button class="btn btn-sm btn-primary" type="button" modify tid="${mtype.tid}" > 修改</button><button data-toggle="button" class="btn btn-sm btn-warning" tid="${mtype.tid}"> 删除</button></td></tr></c:forEach></tbody></table><jsp:include page="pagination.jsp"></jsp:include>
</div>
分页部分前端
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@include file="header.jsp"%>
<html>
<head><title>Title</title>
</head>
<body>
<div class="clearfix text-right"><%--隐藏域--%><input type="hidden" id="pageNo" name="pageNo" value="${mq.pageNo}"><input type="hidden" id="totalPage" value="${page.totalPage}"><ul class="pagination no-margin"><li id="prev" class="disabled"><a href="#">Prev</a></li><c:forEach begin="1" end="${page.totalPage}" var="myPageNo"><li <c:if test="${myPageNo == mq.pageNo}">class="active"</c:if>><a pageNoButton href="#">${myPageNo}</a></li></c:forEach><li id="next"><a href="#">Next</a></li></ul>
</div>
</body>
</html>
上一页和下一页的逻辑
var pageNo = $("#pageNo").val();
var totalPage = $("#totalPage").val();pageNo = parseInt(pageNo);
totalPage = parseInt(totalPage);
//如果已经到首页和尾页,并且只有一页
if (pageNo == 1 && pageNo == totalPage) {$("#prev").addClass("disabled");$("#next").addClass("disabled");
}//如果在首页,且不只有一页
if (pageNo == 1 && pageNo < totalPage) {$("#prev").addClass("disabled");$("#next").removeClass("disabled");
}//如果不只有一页,且不在首页和尾页
if (pageNo > 1 && pageNo < totalPage) {$("#prev").removeClass("disabled");$("#next").removeClass("disabled");
}//如果不只有一页,且不在尾页
if (pageNo > 1 && pageNo == totalPage) {$("#prev").removeClass("disabled");$("#next").addClass("disabled");
}$("#prev").click(function () {$("#pageNo").val(--pageNo);$("#txForm").submit();
})$("#next").click(function () {$("#pageNo").val(++pageNo);$("#txForm").submit();
})$("a[pageNoButton]").click(function () {var pageNo = $(this).html();$("#pageNo").val(pageNo);$("#txForm").submit();
})
相关文章:

SSM虾米音乐项目2--分页查询
1.分页查询的底层逻辑 首先根据用户输入的流派,进行模糊查询根据查询的数据进行分页需要前端用户提供pageNo(当前页数)和pageSize(每页的数据量)并且要从后端计算count(总数据量)和totalPage(总页数),以及startNum(每页开始的记录)从而将对应的页面数据…...
nodejs 获取本地局域网 ip 扫描本地端口
因为傻逼老板的垃圾需求,不得不成长 示例代码: 获取本地局域网 ip 地址: 需要注意的是:如果存在虚拟机网络,则返回的是虚拟机网络的 ipv4 地址 import os from os; export const getLocalIp () > {const in…...
区块链签名种类
1. eth_sign 简介:最早实现的签名方法,用于对任意数据进行签名。签名内容:直接对原始消息的哈希值进行签名。特点: 安全性较低,因为签名的消息没有明确的上下文或结构。很容易被滥用,攻击者可以伪造签名内…...
【062B】基于51单片机无线病房呼叫系统(+时间)【Keil程序+报告+原理图】
☆、设计硬件组成:51单片机最小系统NRF24L01无线模块DS1302时钟芯片LCD1602液晶显示按键设置蜂鸣器LED灯。 1、本设计采用STC89C51/52、AT89C51/52、AT89S51/52作为主控芯片,采用LCD1602液晶显示呼叫信息,系统共有两个板子(一个接…...

突破空间限制!从2D到3D:北大等开源Lift3D,助力精准具身智能操作!
文章链接:https://arxiv.org/pdf/2411.18623 项目链接:https://lift3d-web.github.io/ 亮点直击 提出了Lift3D,通过系统地提升隐式和显式的3D机器人表示,提升2D基础模型,构建一个3D操作策略。 对于隐式3D机器人表示&a…...

【pyspark学习从入门到精通24】机器学习库_7
目录 聚类 在出生数据集中寻找簇 主题挖掘 回归 聚类 聚类是机器学习中另一个重要的部分:在现实世界中,我们并不总是有目标特征的奢侈条件,因此我们需要回归到无监督学习的范式,在那里我们尝试在数据中发现模式。 在出生数据…...
Echart折线图属性设置 vue2
Echart折线图 官方配置项手册 Documentation - Apache ECharts 下面代码包含:设置标题、线条样式、图例圆圈的样式、显示名称格式、图片保存、增加Y轴目标值 updateChart(data) {const sortedData data.slice().sort((a, b) > new Date(a.deviceTime) - ne…...

LabVIEW-简单串口助手
LabVIEW-简单串口助手 串口函数VISA配置串口VISA写入函数VISA读取函数VISA资源名称按名称解除捆绑 函数存放位置思维导图主体界面为以下 串口函数 VISA配置串口 VISA写入函数 VISA读取函数 VISA资源名称 按名称解除捆绑 函数存放位置 思维导图 主体界面为以下 从创建好的“枚举…...

Linux下,用ufw实现端口关闭、流量控制(二)
本文是 网安小白的端口关闭实践 的续篇。 海量报文,一手掌握,你值得拥有,让我们开始吧~ ufw 与 iptables的关系 理论介绍: ufw(Uncomplicated Firewall)是一个基于iptables的前端工具…...

C#开发-集合使用和技巧(九)Join的用法
在C#中,IEnumerable 的 Join 方法用于根据键将两个序列中的元素进行关联。Join 方法通常用于执行类似于 SQL 中的内连接操作。以下是 Join 方法的基本用法: 基本语法 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult…...

Dockerfile容器镜像构建技术
文章目录 1、容器回顾1_容器与容器镜像之间的关系2_容器镜像分类3_容器镜像获取的方法 2、其他容器镜像获取方法演示1_在DockerHub直接下载2_把操作系统的文件系统打包为容器镜像3_把正在运行的容器打包为容器镜像 3、Dockerfile介绍4、Dockerfile指令1_FROM2_RUN3_CMD4_EXPOSE…...

Github 2024-12-01 开源项目月报 Top20
根据Github Trendings的统计,本月(2024-12-01统计)共有20个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10TypeScript项目9Go项目2HTML项目1Shell项目1Jupyter Notebook项目1屏幕截图转代码应用 创建周期:114 天开发语言:TypeScript, Py…...
Spring Boot 3项目集成Swagger3教程
Spring Boot 3项目集成Swagger3教程 ?? 前言 欢迎来到我的小天地,这里是我记录技术点滴、分享学习心得的地方。?? ?? 技能清单 编程语言:Java、C、C、Python、Go、前端技术:Jquery、Vue.js、React、uni-app、EchartsUI设计: Element-u…...

NISP信息安全一级考试200道;免费题库;大风车题库
下载链接:大风车题库-文件 大风车题库网站:大风车题库 大风车excel(试题转excel):大风车excel...

Android ConstraintLayout 约束布局的使用手册
目录 前言 一、ConstraintLayout基本介绍 二、ConstraintLayout使用步骤 1、引入库 2、基本使用,实现按钮居中。相对于父布局的约束。 3、A Button 居中展示,B Button展示在A Button正下方(距离A 46dp)。相对于兄弟控件的约束…...
在网安中什么是白帽子
在网络安全领域,白帽子是指那些专门从事网络安全研究,帮助企业或个人发现并修复安全漏洞的专家。以下是对白帽子的详细解释: 一、定义与角色 白帽子是网络安全领域的术语,通常指那些具备专业技能和知识的网络安全专家。他们的工作…...
软件专业科目难度分级 你输在了哪里?
感想: 我把我们现在软件专业学的东西分了个难度级别 级别描述视角服务对象例子0 基本软件的使用用户-Photoshop wps ssms等1 软件的原理开发者用户各种编程语言2软件的原理的原理开发者开发者各种函数的深层定义,数据结构等 0级就是咱们平时用的那些软…...

微信小程序实现图片拖拽调换位置效果 -- 开箱即用
在编写类似发布朋友圈功能的功能时,需要实现图片的拖拽排序,删除图片等功能。 博主的小程序首页也采用了该示例代码,可以在威信中搜索: 我的百宝工具箱 或者复制后面的🔗在手机打开: #小程序://百宝工具箱/…...
关于“浔川AI翻译”使用情况的调研报告
关于“浔川 AI 翻译”使用情况的调研报告 随着全球化进程加速及外语学习需求攀升,AI 翻译工具愈发普及。“浔川 AI 翻译”作为行业产品之一,为了解其市场表现与用户反馈,特开展本次问卷调查,现将关键结果汇报如下。 一、样本概…...
《芯片:科技之核,未来之路》
《芯片:科技之核,未来之路》 一、芯片的定义与重要性二、芯片的应用领域(一)新能源领域(二)信息通讯设备领域(三)4C 产业(四)智能电网领域(五&…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...