SSM虾米音乐项目2--分页查询

news2025/1/20 3:48:24

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){//如果不能整除的话,需要取整+1
            totalPage++;
        }
        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();
    }

    @Override
    public 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 {
    @Autowired
    private 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;

    @Override
    public void insert(T t) {
        baseDao.insert(t);
    }

    @Override
    public T selectByPrimaryKey(Integer id) {
        return baseDao.selectByPrimaryKey(id);
    }

    @Override
    public void deleteByPrimaryKey(Integer id) {
        baseDao.deleteByPrimaryKey(id);
    }

    @Override
    public void updateByPrimaryKeySelective(T t) {
        baseDao.updateByPrimaryKeySelective(t);
    }

    @Override
    public List<T> selectObjectAll() {
        return baseDao.selectObjectAll();
    }
    //想办法给要返回的page对象所有属性赋值的过程
    @Override
    public 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;

   @Autowired
   public 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();
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2255819.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

debian编译失败

A、缘由和分析 debian的代码在删除该路径下的2个包后&#xff0c; 重新全编&#xff0c;编译不过的问题。 至于我为什么删除这2个包&#xff0c;这是因为在sdk第一次编译时一些文件已经打包进去了&#xff0c;我现在的修改无法更新进img中&#xff0c;而现在我的项目中不需要…

Thonny IDE + MicroPython + ESP32 + A9G 发短信打电话

A9G模块的使用说明 详见该博客&#xff1a;a9gdfgdfhguyiuh-CSDN博客 接线 ESP32 DEVKIT_C A9G GND GND D23 RX A9G开发板用板载MiniUSB&#xff08;安卓口&#xff09;供电 代码 from machine import UART # 导入串口模块 # import timeUART0 UART1 UART2 TX …

在GITHUB上传本地文件指南(详细图文版)

这份笔记简述了如何在GITHUB上上传文件夹的详细策略。 既是对自己未来的一个参考&#xff0c;又希望能给各位读者带来帮助。 详细步骤 打开目标文件夹&#xff08;想要上传的文件夹&#xff09; 右击点击git bash打开 GitHub创立新的仓库后&#xff0c;点击右上方CODE绿色按…

沈阳工业大学《2024年827自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《沈阳工业大学827自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2024年真题 Part1&#xff1a;2024年完整版真题 2024年真题

初始化webpack应用示例

1、初始化npm mkdir webpack_test cd webpack_test npm init 2、安装webpack依赖 npm install webpack webpack-cli -D 3、添加文件夹&#xff0c;入口文件 mkdir src touch index.js touch add-content.js 文件夹结构 index.js import addContent from "./add-cont…

重邮+数字信号处理实验三:z变换及离散LTI系统的z域分析

实验目的&#xff1a; &#xff08; 1 &#xff09;学会运用 Matlab 求离散时间信号的有理函数 z 变换的部分分式展开&#xff1b; &#xff08; 2 &#xff09;学会运用 Matlab 分析离散时间系统的系统函数的零极点&#xff1b; &#xff08; 3 &#xff09;学会运用 …

前端开发底层逻辑全解析

前端开发就像是构建一座数字大厦的外表装饰与交互系统&#xff0c;而理解其底层逻辑则是打好坚实基础的关键。今天&#xff0c;我们就来深入剖析前端开发的底层逻辑。 一、浏览器的工作机制&#xff1a;幕后的魔法手 当我们在浏览器中打开一个网页时&#xff0c;一系列复杂的操…

MySQL -- CURD(下)

1. Update 修改 1.1 语法 对符合条件的结果进⾏列值更新 UPDATE [LOW_PRIORITY] [IGNORE] table_referenceSET assignment [, assignment] ...[WHERE where_condition][ORDER BY ...][LIMIT row_count]1.2 示例 将吕布的数学成绩改为99分 update exam set math 99 where …

【计算机网络】 —— 数据链路层(壹)

文章目录 前言 一、概述 1. 基本概念 2. 数据链路层的三个主要问题 二、封装成帧 1. 概念 2. 帧头、帧尾的作用 3. 透明传输 4. 提高效率 三、差错检测 1. 概念 2. 奇偶校验 3. 循环冗余校验CRC 1. 步骤 2. 生成多项式 3. 例题 4. 总结 四、可靠传输 1. 基本…

亚马逊 aws-waf-token 算法生成,协议逆向,通杀!!!

声明 本文章中所有内容仅供学习交流&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01; 难度不大&#xff0c;核…

SpringBoot 赋能家乡特色推荐系统:高效架构与前沿技术集成

1 绪 论 1.1课题背景与意义 在Internet高速发展的今天&#xff0c;计算机的应用几乎完全覆盖我们生活的各个领域&#xff0c;互联网在经济&#xff0c;生活等方面有着举足轻重的地位&#xff0c;成为人们资源共享&#xff0c;信息快速传递的重要渠道。在中国&#xff0c;网上管…

肥羊直播 1.0.2 |频道非常丰富的高清画质电视直播软件

肥羊直播App是一款专为电视用户设计的直播软件&#xff0c;提供丰富多彩的直播内容&#xff0c;包括央视、卫视、综合、地方、卡通动漫、娱乐、历史古装和电影等频道。该软件支持多种设备&#xff0c;如智能电视、高清机顶盒和安卓手机&#xff0c;为用户带来便捷且高清的观看体…

基础加/解密程序V2.0(Ascll码加减实现) txt保存密钥

Hello大家好&#xff0c;这次我对上篇博客&#xff08;基础加/解密程序&#xff08;Ascll码加减实现&#xff09;-CSDN博客&#xff09;中的代码略加修改&#xff0c;退出了2.0版本&#xff0c;这次我加入了txt输入/出流&#xff0c;使得可随时对密钥进行更改。不过在使用前&am…

代码随想录算法训练营day50|动态规划12

不同的子序列 给定一个字符串 s 和一个字符串 t &#xff0c;计算在 s 的子序列中 t 出现的个数。、 编辑距离中的删除元素&#xff0c;其实就是直接变数字&#xff0c;其只删除原来的较长的数组里的元素 递推模拟&#xff0c;使用s的最后一个元素匹配&#xff0c;或者删除…

keil报错---connection refused due to device mismatch

解决办法如下&#xff1a; 记得改成1 把Enable取消

黑森林实验室发布FLUX.1 Tools控制套件,全面介绍

FLUX.1 Tools是什么 FLUX.1 Tools 是由 Black Forest Labs 发布的一套模型工具&#xff0c;旨在为文本到图像模型 FLUX.1 提供更多的控制和可操作性&#xff0c;使得对真实和生成图像的修改和重新创作成为可能。这套工具包括四个核心功能&#xff1a;FLUX.1 Fill、FLUX.1 Dept…

【包教包会】CocosCreator3.x——重写Sprite,圆角、3D翻转、纹理循环、可合批调色板、不影响子节点的位移旋转缩放透明度

一、效果演示 重写Sprite组件&#xff0c;做了以下优化&#xff1a; 1、新增自变换&#xff0c;在不影响子节点的前提下位移、旋转、缩放、改变透明度 新增可合批调色板&#xff0c;支持色相、明暗调节 新增圆角矩形、3D透视旋转、纹理循环 所有功能均支持合批、原生平台&…

AI 语音:IIElevenLabs 如何通过文本训练出新的声音

网址&#xff1a;Free Text to Speech & AI Voice Generator | ElevenLabs 1&#xff09;点击添加新的声音 2&#xff09;根据需要选择 3&#xff09;比如我选择第一个&#xff08;从文本提示设计一个全新的声音&#xff09; 4&#xff09;通过中文将想要的声音要求翻译成…

Vant UI +Golang(gin) 上传文件

前端基本用法&#xff1a;点击查看 实现代码&#xff1a; const afterRead (file) > {console.log(file);//set content-type to multipart/form-dataconst formData new FormData();formData.append("file", file.file);request.POST("/api/v1/users/up…

2021 年“泰迪杯”数据分析技能赛B 题肥料登记数据分析

2021 年“泰迪杯”数据分析技能赛B 题肥料登记数据分析 完整代码请私聊 博主 # 一、背景 肥料是农业生产中一种重要的生产资料&#xff0c;其生产销售必须遵循《肥料登记管理办法》&#xff0c;依法在农业行政管理部门进行登记。各省、自治区、直辖市人民政府农业行政主管部门主…