Web项目利用MybatisPlus进行分页查询

之前在写博客系统前台页面的时候,遇到了利用mp进行分页查询的情况,由于涉及到的知识点相对较为重要,固写一篇博客以此巩固。

一、功能需求

在首页和分类页面都需要查询文章列表。

  • 首页:查询所有的文章
  • 分类页面:查询对应分类下的文章
  • 要求:①只能查询正式发布的文章   ②置顶的文章要显示在最前面

1.1 接口设计

Swagger2如下:

请求参数如下:

 响应如下:

二、代码实现

由于我们涉及了利用mp进行分页的情况,所以我们需要先配置mp的配置类:

@Configuration
public class MbatisPlusConfig {/*** 3.4.0之后版本* @return*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());return mybatisPlusInterceptor;}
}

 在ArticleController中:

@RestController
@RequestMapping("/article")
public class ArticleController {@Autowiredprivate ArticleService articleService;@GetMapping("/articleList")public ResponseResult articleList(Integer pageNum,Integer pageSize,Long categoryId){return articleService.articleList(pageNum,pageSize,categoryId);}}

分析:

这里前端传来的请求参数类型是 query 类型,如果我们需要解决前端和后端中命名不一致的问题,可以使用@RequestParms注解。关于SpringMVC的相关知识可以移步博客的另一篇博客:

SpringMVC的三大功能

ArticleService中: 

在ArticleServiceImpl中: 


@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {@Autowiredprivate CategoryService categoryService;@Overridepublic ResponseResult articleList(Integer pageNum, Integer pageSize, Long categoryId) {//查询条件LambdaQueryWrapper<Article> lambdaQueryWrapper = new LambdaQueryWrapper<>();// 如果 有categoryId 就要 查询时要和传入的相同lambdaQueryWrapper.eq(Objects.nonNull(categoryId)&&categoryId>0 ,Article::getCategoryId,categoryId);// 状态是正式发布的lambdaQueryWrapper.eq(Article::getStatus,SystemConstants.ARTICLE_STATUS_NORMAL);// 对isTop进行降序lambdaQueryWrapper.orderByDesc(Article::getIsTop);//分页查询Page<Article> page = new Page<>(pageNum,pageSize);page(page,lambdaQueryWrapper);List<Article> articles = page.getRecords();//查询categoryNamearticles.stream().map(article -> article.setCategoryName(categoryService.getById(article.getCategoryId()).getName())).collect(Collectors.toList());//articleId去查询articleName进行设置
//        for (Article article : articles) {
//            Category category = categoryService.getById(article.getCategoryId());
//            article.setCategoryName(category.getName());
//        }//封装查询结果List<ArticleListVo> articleListVos = BeanCopyUtils.copyBeanList(page.getRecords(), ArticleListVo.class);PageVo pageVo = new PageVo(articleListVos,page.getTotal());return ResponseResult.okResult(pageVo);}
}

 分析:

这里涉及到蛮多知识点的,如VO、Bean工具类拷贝等。

我们这里重点关注data里面的数据,外部的code、data、msg为我自定义的响应类 ReponseResult。

这里其实就涉及到VO的概念,这个data里面其实可以看出来,应该是由两个部分组成,一个是rows,一个是total。

因此,我们需要创建一个PageVo的概念:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageVo {private List rows;private Long total;
}

而这个rows我们使用List集合接收,但是我们仔细观察Article类,发现它实际的字段是多于我们需要传输给前端的字段的,并且有些字段Article类是没有的,这里为了不破坏Article的耦合性,所以我们又需要创建一个ArticleListVo对象:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Data
@NoArgsConstructor
@AllArgsConstructor
public class ArticleListVo {private Long id;//标题private String title;//文章摘要private String summary;//所属分类名private String categoryName;//缩略图private String thumbnail;//访问量private Long viewCount;private Date createTime;}

 Article对象如下:

import java.util.Date;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;/*** 文章表(Article)表实体类** @author makejava* @since 2022-02-01 11:36:28*/
@SuppressWarnings("serial")
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("sg_article")
@Accessors(chain = true)
public class Article  {@TableIdprivate Long id;//标题private String title;//文章内容private String content;//文章摘要private String summary;//所属分类idprivate Long categoryId;@TableField(exist = false)private String categoryName;//缩略图private String thumbnail;//是否置顶(0否,1是)private String isTop;//状态(0已发布,1草稿)private String status;//访问量private Long viewCount;//是否允许评论 1是,0否private String isComment;@TableField(fill = FieldFill.INSERT)private Long createBy;@TableField(fill = FieldFill.INSERT)private Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private Long updateBy;@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;//删除标志(0代表未删除,1代表已删除)private Integer delFlag;public Article(Long id, long viewCount) {this.id = id;this.viewCount = viewCount;}
}

细心观察可以发现,Article类虽然有大部分的ArticleListVo对象的属性,但是却缺少一个categoryName属性:

这里是因为Article表是没有这个属性的,所以我们加入这个@TableFiled注解,来避免mp在进行ORM映射的时候找不到属性而报错。

给Article类添加这个属性只是为了方便后面进行Bean拷贝而已,因为Article类必须有这个属性,才能将这个属性拷贝到我们要传输给前端的ArticleListVo属性。

可以通过for循环或者是Stream流的方式来将Article这个类的CategoryName属性填充完毕:

最后再进行Bean拷贝:

package com.fox.utils;import org.springframework.beans.BeanUtils;import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;public class BeanCopyUtils {//由于这是工具类,就直接将构造方法设置为私有的private BeanCopyUtils() {}public static <T> T copyBean(Object source,Class<T> clazz) {//创建目标对象T result = null;try {result = clazz.newInstance();//实现属性copyBeanUtils.copyProperties(source, result);} catch (Exception e) {e.printStackTrace();}//返回结果return result;}public static <E,T> List<T> copyBeanList(List<E> list, Class<T> clazz){List<T> result = new ArrayList<>();for (E e : list) {T t = copyBean(e, clazz);result.add(t);}return result;
//        return list.stream()
//                .map(E -> copyBean(E, clazz))
//                .collect(Collectors.toList());}
}

需要注意的是,这里在进行Bean拷贝的时候,其会根据属性名自动匹配,但是需要保证拷贝的双方属性的类型是一致的,不然会转换失败,比如 Article  类中 id属性的类型是 long,而其Vo对象的id属性为 Integer,那么就会报错。

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

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

相关文章

[计算机网络]---序列化和反序列化

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、再谈协议…

第8讲项目整合SpringSecurity

pom.xml加下springsecurity依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId> </dependency>SecurityConfig配置文件&#xff1a; package com.java1234.config;imp…

【NLP】MHA、MQA、GQA机制的区别

Note LLama2的注意力机制使用了GQA。三种机制的图如下&#xff1a; MHA机制&#xff08;Multi-head Attention&#xff09; MHA&#xff08;Multi-head Attention&#xff09;是标准的多头注意力机制&#xff0c;包含h个Query、Key 和 Value 矩阵。所有注意力头的 Key 和 V…

牛客2024年除夕娱乐赛(题解)

比赛地址 : 牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A 看题面然后猜!!! #include<bits/stdc.h> using namespace std; int main(){cout << "原神启动" << endl; } B 也是看题面然后猜 : #include<bits/stdc.…

springboot189基于SpringBoot电商平台的设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

macOS Sonoma 14.4beta3(23E5196e)发布【附黑/白苹果镜像】

系统介绍 黑果魏叔2 月 14 日消息&#xff0c;苹果今日向 Mac 电脑用户推送了 macOS 14.4 开发者预览版 Beta 3 更新&#xff08;内部版本号&#xff1a;23E5196e&#xff09;&#xff0c;本次更新距离上次发布隔了 7 天。 魏叔查询支持文档&#xff0c;发现 macOS 14.4 Beta…

安全基础~通用漏洞5

文章目录 知识补充CSRFSSRFxss与csrf结合创建管理员账号 知识补充 NAT&#xff1a;网络地址转换&#xff0c;可以将IP数据报文头中的IP地址转换为另一个IP地址&#xff0c;并通过转换端口号达到地址重用的目的。即通过将一个外部IP地址和端口映射更大的内部IP地址集来转换IP地…

ICLR 2023#Learning to Compose Soft Prompts for Compositional Zero-Shot Learning

组合零样本学习&#xff08;CZSL&#xff09;中Soft Prompt相关工作汇总&#xff08;一&#xff09; 文章目录 组合零样本学习&#xff08;CZSL&#xff09;中Soft Prompt相关工作汇总&#xff08;一&#xff09;ICLR 2023#Learning to Compose Soft Prompts for Compositional…

嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第五天-ARM Linux编程之file_operations详解 (物联技术666)

链接&#xff1a;https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd1688 提取码&#xff1a;1688 struct file_operations{ struct module *owner; // 指向拥有该结构的模块的指针&#xff0c;避免正在操作时被卸载&#xff0c;一般为初始化THIS_MODULES loff_t &#…

透光卓越,光耦继电器的独特特点全面解析

光耦继电器作为电子控制系统中的核心元件&#xff0c;其光电隔离技术为其独特之处。通过光电隔离技术&#xff0c;光耦继电器实现了输入和输出之间的电气隔离&#xff0c;有效阻止了高电压与低电压之间的直接接触。这项技术不仅提高了系统的安全性&#xff0c;还有效减少了电气…

Vue练习1:组件开发1(头像组件)

样式预览 注释代码 <template><div class"img-box":style"{ //动态style必须为对象width: size rem,height: size rem}"><imgclass"avatar-img":src"url" //动态url/></div> </templ…

【DDD】学习笔记-聚合设计原则

聚合设计原则 对比对象图和聚合&#xff0c;我们认为引入聚合的目的是控制对象之间的关系&#xff0c;这实则是引入聚合的技术原因。领域驱动设计引入聚合&#xff08;Aggregate&#xff09;来划分对象之间的边界&#xff0c;在边界内保证所有对象的一致性&#xff0c;并在对象…

C语言从零实现贪吃蛇小游戏

制作不易&#xff0c;点赞关注一下呗&#xff01;&#xff01;&#xff01; 文章目录 前言一. 技术要点二、WIN32API介绍三、贪吃蛇游戏设计与分析 1.游戏开始前的初始化 2.游戏运行的逻辑 总结 前言 当我们掌握链表这样的数据结构之后&#xff0c;我们就可以用它来…

比特币 P2PKH、P2SH

标准脚本P2PKH、P2SH 区块链重要基础知识7-1——标准脚本P2PKH、P2SH-CSDN博客 比特币中P2SH(pay-to-script-hash)多重签名的锁定脚本和解锁脚本 https://www.cnblogs.com/itlgl/p/10419325.html

wayland(xdg_wm_base) + egl + opengles 使用FBO渲染到纹理实例(六)

文章目录 前言一、FBO介绍1. FBO 简介2. FBO的关键组成部分3. FBO的基本工作流程4. FBO 实现渲染到纹理5. FBO 实现离屏渲染二、FBO 实现渲染到纹理的代码实例1. egl_wayland_texture3_2.c2. xdg-shell-client-protocol.h 和 xdg-shell-protocol.c3. 编译4. 运行总结参考资料前…

京东护网面试题汇总

1 、JNI 函数在 java 中函数名为 com.didi.security.main,C 中的函数名是什么样的&#xff1f; com_didi_security_mian java.com.didi.security.main 2 、Frida 和 Xposed 框架&#xff1f; 3 、SSRF 利用方式&#xff1f; 4 、宏病毒&#xff1f; 5 、APP 加壳&a…

黑群晖一键修复:root、AME、DTS、转码、CPU型号等

食用方法&#xff1a;SSH连接群晖使用临时root权限执行 AME3.x激活补丁 只适用于x86_64的&#xff1a;DSM7.x Advanced Media Extensions (AME)版本3.0.1-2004、3.1.0-3005 激活过程需要下载官方的解码包&#xff0c;过程较慢&#xff0c;耐心等待。。。 DSM7.1和7.2的AME版…

Rust - 变量与数据的交互方式(move)

变量与数据的交互方式 - 移动 Rust 中的多个变量可以采用一种比较独特的方式和同一个数据进行交互&#xff0c;如下代码所示&#xff0c;将变量x的值赋给y&#xff1a; fn main() {let x 1;let y x; }我们大概可以推论出上述代码的原理&#xff1a;将1这个整数绑定给x变量&…

建造者模式-Builder Pattern

原文地址:https://jaune162.blog/design-pattern/builder-pattern/ 引言 现在一般大型的业务系统中的消息通知的形式都会有多种,比如短信、站内信、钉钉通知、邮箱等形式。虽然信息内容相同,但是展现形式缺不同。如短信使用的是纯文本的形式,钉钉使用的一般是Markdown的形…

odoo自定义widget组件两种方式

odoo 自定义一个widget 方式一 js crossnow.define(your_module.custom_widget, function (require) {"use strict";const core require(web.core);const QWeb core.qweb;const {useState, useRef} owl.hooks;// 方式1 函数方式const AbstractField require(w…