【JAVA】黑马MybatisPlus 学习笔记【终】【插件功能】

4.插件功能

MybatisPlus提供了很多的插件功能,进一步拓展其功能。目前已有的插件有:

  • PaginationInnerInterceptor:自动分页
  • TenantLineInnerInterceptor:多租户
  • DynamicTableNameInnerInterceptor:动态表名
  • OptimisticLockerInnerInterceptor:乐观锁
  • IllegalSQLInnerInterceptorsql 性能规范
  • BlockAttackInnerInterceptor:防止全表更新与删除

注意:
使用多个分页插件的时候需要注意插件定义顺序,建议使用顺序如下:

  • 多租户,动态表名
  • 分页,乐观锁
  • sql 性能规范,防止全表更新与删除

这里我们以分页插件为里来学习插件的用法。

4.1.分页插件

在未引入分页插件的情况下,MybatisPlus是不支持分页功能的,IServiceBaseMapper中的分页方法都无法正常起效。

所以,我们必须配置分页插件。

4.1.1.配置分页插件

在项目中新建一个配置类:
在这里插入图片描述
其代码如下:

package com.itheima.mp.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MybatisConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {// 初始化核心插件MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 添加分页插件PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);paginationInnerInterceptor.setMaxLimit(1000L);interceptor.addInnerInterceptor(paginationInnerInterceptor);return interceptor;}
}
4.1.2.分页API

编写一个分页查询的测试:

  @Testvoid testPageQuery(){int pageNo = 1, pageSize = 2;//     1.准备分页条件//     1.1.分页条件Page<User> page = Page.of(pageNo, pageSize);//     1.2.排序条件 (先按照balance 升序,如果存在一致的balance 再按照 id 进行升序排序)page.addOrder(new OrderItem("balance",true));page.addOrder(new OrderItem("id",true));//     2.分页查询Page<User> p = userService.page(page);//     3.解析long total = p.getTotal(); // 总记录数System.out.println("total = "+total);long pages = p.getPages(); // 总页数System.out.println("pages = "+pages);List<User> users = p.getRecords(); // 分页结果users.forEach(System.out::println);}

运行的SQL如下:
在这里插入图片描述

4.2.通用分页实体

现在要实现一个用户分页查询的接口,接口规范如下:
在这里插入图片描述
返回值如下:
在这里插入图片描述

这里需要定义3个实体:

  • UserQuery:分页查询条件的实体,包含分页排序参数过滤条件
  • PageDTO:分页结果实体,包含总条数总页数当前页数据
  • UserVO:用户页面视图实体
4.2.1.实体

由于UserQuery之前已经定义过了,并且其中已经包含了过滤条件,具体代码如下:

package com.itheima.mp.domain.query;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;@Data
@ApiModel(description = "用户查询条件实体")
public class UserQuery {@ApiModelProperty("用户名关键字")private String name;@ApiModelProperty("用户状态:1-正常,2-冻结")private Integer status;@ApiModelProperty("余额最小值")private Integer minBalance;@ApiModelProperty("余额最大值")private Integer maxBalance;
}

其中缺少的仅仅是分页条件,而分页条件不仅仅用户分页查询需要,以后其它业务也都有分页查询的需求。因此建议将分页查询条件单独定义为一个PageQuery实体:

在这里插入图片描述

PageQuery是前端提交的查询参数,一般包含四个属性:

  • pageNo:页码
  • pageSize:每页数据条数
  • sortBy:排序字段
  • isAsc:是否升序
package com.itheima.mp.domain.query;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;@Data
@ApiModel(description = "分页查询实体")
public class PageQuery {@ApiModelProperty("页码")private Long pageNo;@ApiModelProperty("页码")private Long pageSize;@ApiModelProperty("排序字段")private String sortBy;@ApiModelProperty("是否升序")private Boolean isAsc;
}

然后,让我们的UserQuery继承这个实体:
在这里插入图片描述

分页实体PageDTO:
在这里插入图片描述

代码如下:

package com.itheima.mp.domain.dto;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.util.List;@Data
@ApiModel(description = "分页结果")
public class PageDTO<T> {@ApiModelProperty("总条数")private Long total;@ApiModelProperty("总页数")private Long pages;@ApiModelProperty("集合")private List<T> list;
}

最后是UserVO,在之前有写过:
在这里插入图片描述

4.2.2.开发接口

UserController中定义分页查询用户的接口:
在这里插入图片描述
代码如下:

  @ApiOperation("根据分页条件查询用户的接口")@GetMapping("/page")public PageDTO<UserVO> queryUsersPage(UserQuery query){return userService.queryUsersPage(query);}

然后在IUserService中创建queryUsersPage方法:

PageDTO<UserVO> queryUsersPage(PageQuery query);

接下来,在UserServiceImpl中实现该方法:

  @Overridepublic PageDTO<UserVO> queryUsersPage(UserQuery query) {String name = query.getName();Integer status = query.getStatus();Integer maxBalance = query.getMaxBalance();Integer minBalance = query.getMinBalance();// 1.1.分页条件Page<User> page = Page.of(query.getPageNo(), query.getPageSize());// 1.2.排序条件if (StrUtil.isNotBlank(query.getSortBy())) { // 排序条件不为空page.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));} else { // 排序条件为空,默认按照更新时间进行降序排序page.addOrder(new OrderItem("update_time", false));}// 2.分页查询Page<User> p = lambdaQuery().like(name != null, User::getUsername, name).eq(status != null, User::getStatus, status).ge(minBalance != null, User::getBalance, minBalance).le(maxBalance != null, User::getBalance, maxBalance).page(page);// 3.封装VO结果PageDTO<UserVO> dto = new PageDTO<>();// 3.1.总条数dto.setTotal(p.getTotal());// 3.2.总页数dto.setPages(p.getPages());// 3.3.当前页数据List<User> records = p.getRecords();if (CollUtil.isEmpty(records)) {dto.setList(Collections.emptyList());return dto;}// 3.4.拷贝user的vodto.setList(BeanUtil.copyToList(records, UserVO.class));// 4.返回return dto;}

启动项目,在测试效果:
在这里插入图片描述

4.2.3.改造PageQuery实体

在刚才的代码中,从PageQueryMybatisPlusPage之间转换的过程还是比较麻烦的。

我们完全可以在PageQuery这个实体中定义一个工具方法,简化开发。
像这样:

在这里插入图片描述

package com.itheima.mp.domain.query;import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;@Data
public class PageQuery {private Integer pageNo;private Integer pageSize;private String sortBy;private Boolean isAsc;public <T>  Page<T> toMpPage(OrderItem ... orders){// 1.分页条件Page<T> p = Page.of(pageNo, pageSize);// 2.排序条件// 2.1.先看前端有没有传排序字段if (sortBy != null) {p.addOrder(new OrderItem(sortBy, isAsc));return p;}// 2.2.再看有没有手动指定排序字段if(orders != null){p.addOrder(orders);}return p;}public <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc){return this.toMpPage(new OrderItem(defaultSortBy, isAsc));}public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {return toMpPage("create_time", false);}public <T> Page<T> toMpPageDefaultSortByUpdateTimeDesc() {return toMpPage("update_time", false);}
}

这样可以省去对从PageQueryMybatisPlusPage的转换,UserServiceImpl简化如下:
在这里插入图片描述

Page<User> page = query.toMpPageDefaultSortByUpdateTimeDesc();
4.2.4.改造PageDTO实体

在查询出分页结果后,数据的非空校验,数据的vo转换都是模板代码,编写起来很麻烦。
我们完全可以将其封装到PageDTO的工具方法中,简化整个过程:

在这里插入图片描述
代码如下:

package com.itheima.mp.domain.dto;import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "分页结果")
public class PageDTO<T> {@ApiModelProperty("总条数")private Long total;@ApiModelProperty("总页数")private Long pages;@ApiModelProperty("集合")private List<T> list;/*** 返回空分页结果* @param p MybatisPlus的分页结果* @param <V> 目标VO类型* @param <P> 原始PO类型* @return VO的分页对象*/public static <V, P> PageDTO<V> empty(Page<P> p){return new PageDTO<>(p.getTotal(), p.getPages(), Collections.emptyList());}/*** 将MybatisPlus分页结果转为 VO分页结果* @param p MybatisPlus的分页结果* @param voClass 目标VO类型的字节码* @param <V> 目标VO类型* @param <P> 原始PO类型* @return VO的分页对象*/public static <V, P> PageDTO<V> of(Page<P> p, Class<V> voClass) {// 1.非空校验List<P> records = p.getRecords();if (records == null || records.size() <= 0) {// 无数据,返回空结果return empty(p);}// 2.数据转换List<V> vos = BeanUtil.copyToList(records, voClass);// 3.封装返回return new PageDTO<>(p.getTotal(), p.getPages(), vos);}/*** 将MybatisPlus分页结果转为 VO分页结果,允许用户自定义PO到VO的转换方式* @param p MybatisPlus的分页结果* @param convertor PO到VO的转换函数* @param <V> 目标VO类型* @param <P> 原始PO类型* @return VO的分页对象*/public static <V, P> PageDTO<V> of(Page<P> p, Function<P, V> convertor) {// 1.非空校验List<P> records = p.getRecords();if (records == null || records.size() <= 0) {// 无数据,返回空结果return empty(p);}// 2.数据转换List<V> vos = records.stream().map(convertor).collect(Collectors.toList());// 3.封装返回return new PageDTO<>(p.getTotal(), p.getPages(), vos);}
}

最终业务简化如下:

在这里插入图片描述
代码如下:

  @Overridepublic PageDTO<UserVO> queryUsersPage(UserQuery query) {String name = query.getName();Integer status = query.getStatus();Integer maxBalance = query.getMaxBalance();Integer minBalance = query.getMinBalance();// 1.构建分页条件Page<User> page = query.toMpPageDefaultSortByUpdateTimeDesc();// 2.分页查询Page<User> p = lambdaQuery().like(name != null, User::getUsername, name).eq(status != null, User::getStatus, status).ge(minBalance != null, User::getBalance, minBalance).le(maxBalance != null, User::getBalance, maxBalance).page(page);// 3.封装返回return PageDTO.of(page, UserVO.class);}

如果是希望自定义POVO的转换过程,可以这样做:

  @Overridepublic PageDTO<UserVO> queryUsersPage(UserQuery query) {String name = query.getName();Integer status = query.getStatus();Integer maxBalance = query.getMaxBalance();Integer minBalance = query.getMinBalance();// 1.构建分页条件Page<User> page = query.toMpPageDefaultSortByUpdateTimeDesc();// 2.分页查询Page<User> p = lambdaQuery().like(name != null, User::getUsername, name).eq(status != null, User::getStatus, status).ge(minBalance != null, User::getBalance, minBalance).le(maxBalance != null, User::getBalance, maxBalance).page(page);// 3.封装返回// return PageDTO.of(page, UserVO.class);return PageDTO.of(page, user -> {// 拷贝属性到VOUserVO vo = BeanUtil.copyProperties(user, UserVO.class);// 用户名脱敏String username = vo.getUsername();vo.setUsername(username.substring(0, username.length() - 2) + "**");return vo;});}

查询的结果如下:

在这里插入图片描述

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

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

相关文章

【Linux】生产者消费者模型(阻塞队列与环形队列)和POSIX信号量

文章目录 一、生产者消费者模型二、基于BlockingQueue的生产者消费者模型1.BlockQueue.hpp2.Task.hpp3.main.cc 三、POSIX信号量四、基于环形队列的生产消费模型1.RingQueue.hpp2.Task.hpp3.main.cc 一、生产者消费者模型 我们这里举一个例子&#xff0c;来解释生产者消费者模…

【数据结构和算法】寻找数组的中心下标

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 前缀和的解题模板 2.1.1 最长递增子序列长度 2.1.2 寻找数组中第 k 大的元素 2.1.3 最长公共子序列…

雷盛红酒和云仓酒庄的优势

多国家采购、多葡萄酒品种、多价位区间的全系列整体品牌形式的雷盛&#xff08;LEESON&#xff09;红酒云仓酒庄&#xff0c;具有以下优势&#xff1a; 1.明星代言。雷盛&#xff08;LEESON&#xff09;品牌系列葡萄酒有幸邀请著名导演张纪中先生担任品牌代言人&#xff0c;为…

什么是天线OTA,怎么通过OTA数据评估产品射频环境情况

1.1 验证项目 产品的器件布局、走线是否合理、电源输入输出设计、纹波控制&#xff0c;铺地回流设计等是否合理. 通过验证产品的天线OTA_TIS项目来作为评估当前的设计是否合理之一&#xff0c;重点验证低频部分&#xff0c;如Band8段数据. 1.2 什么是天线OTA 是指某无线产品…

Vue3使用的Compostion Api和Vue2使用的Options Api有什么不同?

我们介绍Compostion Api和Options Api的区别之前&#xff0c;先来说一下为什么会推出来Composition Api&#xff0c;解决了什么问题&#xff1f; Vue2开发项目使用Options Api存在的问题 代码的可读性和维护性随着组件的变大业务的增多而变得差代码的共享和重用性存在缺点不支…

【Linux】进程查看|fork函数|进程状态

&#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&am…

H.264宏块(Macroblock)概念(运动估计、变换编码、环路滤波)

参考文章&#xff1a;音视频高手课系列5-h264编码基础(宏块原理) 参考文章&#xff1a;切片slice与宏块&#xff0c;运动矢量 文章目录 使用videoEye分析视频宏块示例H.264宏块概念1. 宏块的定义2. 运动估计3. 变换编码4. 环路滤波5. 注意&#xff1a;宏块的概念既适用于帧内编…

基于Java Swing的图书管理系统

一、项目总体架构 本项目基于Java Swing框架&#xff0c;数据库采用的是MySQL。项目文件夹如下&#xff1a; 二、项目截图 1.登录和注册界面 2.用户界面 3.管理员管理图书类别 4.管理员管理书籍 5.管理员管理用户 项目总体包括源代码和课程论文&#xff0c;需要源码的…

通过MobaXterm远程连接Anolis

目录 前言&#xff1a; 一.设置ip 二.远程连接 前言&#xff1a; 小编已经阐述了如何安装Anolis系统&#xff0c;如果有不了解的小伙伴可以查看这一篇博客Anolis安装 这篇博客将会讲述如何远程连接Anolis系统。各位看官拿好板凳&#xff01; 一.设置ip 打开网卡所在位…

西门子PLC通过PROFINET协议与多功能电表通讯

西门子PLC通过PROFINET协议与多功能电表通讯 项目要求 西门子S71200PLC需要通过PROFINET协议和多功能电表通讯&#xff0c;读取线电压、相电压、线电流、相电流、有功功率、无功功率等参数。 项目实施 采用网关NET90-PN-MBT&#xff08;以下简称“网关”&#xff09;&#…

怎么提取视频中的背景音乐?

当我们在刷视频的时候&#xff0c;有时候听到一个背景音乐很好听&#xff0c;但是又不知道歌名&#xff0c;比如英语歌&#xff0c;这个时候我们很难找到这首歌&#xff0c;相信有很多朋友会遇到这样的问题&#xff0c;不知道怎么弄&#xff0c;下面小编给大家推荐一些方法帮助…

Pytorch从零开始实战14

Pytorch从零开始实战——DenseNet SENet算法实战 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——DenseNet SENet算法实战环境准备数据集模型选择开始训练可视化总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#x…

亿赛通电子文档安全管理系统 linkfilterservice 未授权漏洞

产品简介 亿赛通电子文档安全管理系统&#xff0c;&#xff08;简称&#xff1a;CDG&#xff09;是一款电子文档安全加密软件&#xff0c;该系统利用驱动层透明加密技术&#xff0c;通过对电子文档的加密保护&#xff0c;防止内部员工泄密和外部人员非法窃取企业核心重要数据资…

Spring企业开发核心框架

文章目录 Spring企业开发核心框架一、框架前言1. 总体技术体系2. 框架概念和理解 二、Spring Framework简介1. Spring 和 SpringFramework2. SpringFramework主要功能模块3. SpringFramework 主要优势 三、Spring IoC 容器概念1. 组件和组件管理概念2. Spring IoC容器和容器实现…

ALS-运动系统解构

角色握持 角色蓝图&#xff1a;将物体绑在手上 动作蓝图&#xff1a; 将握持动画截取一帧&#xff08;explicit time时间写好&#xff09; 角色替换 在原人物模型下面加一个骨骼体&#xff08;先不用添加模型&#xff09;&#xff0c;重命名为bodymesh AI使用流程 新建一…

品牌如何在线上打造“社交货币”?媒介盒子揭秘

品牌的社交货币&#xff0c;是品牌与消费者的共识身份铸造器。竹筒奶茶、Keep奖牌这类的实体产品作为社交货币&#xff0c;每每能够引爆社交平台&#xff0c;那么品牌能否通过线上平台打造“社交货币”呢&#xff1f;接下来就让媒介盒子和大家聊聊。 一、社交货币是什么 社交货…

6.Nacos

1.单机部署 1.1 官网 https://nacos.io/zh-cn/index.html https://github.com/alibaba/Nacos 1.2.版本说明 https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E 1.3.下载地址 https://github.com/alibaba/nacos/releases/tag/2.2.…

小区跑腿服务

社区跑腿服务是指在社区范围内为居民提供各种便利的服务&#xff0c;包括购物代劳、快递代取、家政服务等。 这种服务的出现&#xff0c;满足了居民生活中诸多需求&#xff0c;受到了广泛的欢迎和认可。 首先&#xff0c;社区跑腿服务方便了居民的日常生活。 居民无需亲自前…

克魔助手工具下载、注册和登录指南

下载安装克魔助手 摘要 本文介绍了如何下载安装克魔助手工具&#xff0c;以及注册和登录流程。通过简单的步骤&#xff0c;用户可以轻松获取并使用该工具&#xff0c;为后续的手机应用管理操作做好准备。 引言 克魔助手是一款免费的手机管理工具&#xff0c;通过该工具用户…

文章解读与完整程序——《考虑“源-荷-储”协同互动的主动配电网优化调度研究》

摘要&#xff1a;伴随智能电网的建设和清洁能源的开发利用,配电网中的负荷类型呈现多元化发展,分布式电源、可控负荷、储能等资源的增加让单向潮流的传统配电网逐渐向双向潮流的主动配电网结构转变。在能源结构转变的同时,清洁能源自身的随机性和波动性给配电网带来了更大的调峰…