[MyBatis-Plus]扩展功能详解
代码生成
使用MP的步骤是非常固定的几步操作

基于插件, 可以快速的生成基础性的代码

- 安装插件
- 安装完成后重启IEDA
- 连接数据库


- mp是数据库的名字
- ?serverTimezone=UTC 是修复mysql时区, 不加会报错
- 生成代码


- TablePrefix选项是用于去除表名的前缀, 比如根据tb_user表生成实体类User, 就填写tb_
静态工具
业务开发中, 可能会存在service之间互相调用, 如果使用传统的资源注入, 就会出现循环依赖的问题
建议就是service之间的相互调用, 使用DB静态工具进行方法的调用, 避免循环依赖的问题
DB静态工具的方法和IService的方法几乎一样, 只是调用时需要传入字节码

案例1: 改造根据id查询用户的接口, 查询用户的同时, 查询出对应的地址
/*** @author * @since 2023-07-01*/
@Data
@ApiModel(description = "收货地址VO")
public class AddressVO{@ApiModelProperty("id")private Long id;@ApiModelProperty("用户ID")private Long userId;@ApiModelProperty("省")private String province;@ApiModelProperty("市")private String city;@ApiModelProperty("县/区")private String town;@ApiModelProperty("手机")private String mobile;@ApiModelProperty("详细地址")private String street;@ApiModelProperty("联系人")private String contact;@ApiModelProperty("是否是默认 1默认 0否")private Boolean isDefault;@ApiModelProperty("备注")private String notes;
}
@Data
@ApiModel(description = "用户VO实体")
public class UserVO {@ApiModelProperty("用户id")private Long id;@ApiModelProperty("用户名")private String username;@ApiModelProperty("详细信息")private String info;@ApiModelProperty("使用状态(1正常 2冻结)")private UserStatus status;@ApiModelProperty("账户余额")private Integer balance;@ApiModelProperty("用户的收货地址")private List<AddressVO> addresses;}
@Api(tags = "用户管理接口")
@RequestMapping("/users")
@RestController
@RequiredArgsConstructor
public class UserController {private final IUserService userService;@ApiOperation("根据id查询用户接口")@GetMapping("/{id}")public UserVO queryUserById(@ApiParam("用户id") @PathVariable("id") Long id){return userService.queryUserAndAddressById(id);}
}
public interface IUserService extends IService<User> {UserVO queryUserAndAddressById(Long id);}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Overridepublic UserVO queryUserAndAddressById(Long id) {//1,查询用户User user = getById(id);if (user == null || user.getStatus() == UserStatus.FROZEN) {throw new RuntimeException("用户状态异常");}//2查询地址List<Address> addresses = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();//3封装VO//3.1把user的PO转成VOUserVO userVO = BeanUtil.copyProperties(user, UserVO.class);//3.2转地址为VOif (CollUtil.isNotEmpty(addresses)) {userVO.setAddresses(BeanUtil.copyToList(addresses, AddressVO.class));}return userVO;}}
案例2: 改造根据id批量查询的接口, 查询用户的同时, 查询出用户对应的所有地址
@Api(tags = "用户管理接口")
@RequestMapping("/users")
@RestController
@RequiredArgsConstructor
public class UserController {private final IUserService userService;@ApiOperation("根基id批量查询用户接口")@GetMappingpublic List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids) {return userService.queryUserAndAddressByIds(ids);}}
public interface IUserService extends IService<User> {List<UserVO> queryUserAndAddressByIds(List<Long> ids);}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Overridepublic List<UserVO> queryUserAndAddressByIds(List<Long> ids) {//1,查询用户List<User> users = listByIds(ids);if (CollUtil.isNotEmpty(users)) {return Collections.emptyList();}//2,查询地址//2.1获取用户id集合List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());//2.2根据用户id查询地址List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();//2.3转换地址VOList<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);//2.4用户地址集合分组处理, 相同用户的放入一个集合(组)中Map<Long, List<AddressVO>> addressMap = new HashMap<>(0);if (CollUtil.isNotEmpty(addressVOList)) {addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));}//3,转换VO返回List<UserVO> list = new ArrayList<>(users.size());for (User user : users) {//3.1转换USER的PO为VOUserVO vo = BeanUtil.copyProperties(user, UserVO.class);list.add(vo);//3.2转换地址VOvo.setAddresses(addressMap.get(user.getId()));}return list;}}
逻辑删除
逻辑删除就是基于代码逻辑, 模拟删除效果, 不会真正删除数据
- 在表中添加一个字段标记数据是否被删除
- 当删除数据时把标记置为1

- 查询时只查询标记为0的数据

MP提供了逻辑删除功能, 无需改变方法调用的方式, 只需要简单配置, MP就会在底层自动修改CRUE的语句

- 在application.yaml文件中配置逻辑删除的字段名称和值就可以
案例
mybatis-plus:type-aliases-package: com.itheima.mp.domain.poglobal-config:db-config:logic-delete-field: deleted # 配置逻辑删除字段
@SpringBootTest
class IAddressServiceTest {@Autowiredprivate IAddressService addressService;@Testvoid testLogicDelete() {//1,删除addressService.removeById(59L); // 代码是正常删除,但执行的是更新操作,更新deleted字段//2,查询Address address = addressService.getById(59L);System.out.println("address=" + address); // null,已经删除的数据查不到}
}
逻辑删除存在的问题:
- 会导致数据表中的垃圾数据越来越多, 影响查询效率
- SQL中全都要对逻辑删除字段进行判断,影响查询效率
其他方案
- 如果数据不能删除, 可以把在删除之前, 把数据迁移到备份的表中,
- 然后执行删除操作, 这样主表中的数据就比较干净, 而且数据也会保留
枚举处理器
作用: 解决java的enum类型和数据库INT类型的相互转换问题

- 开发过程中, 我们会使用枚举类型 替换 固定数值
- 但数据表中存储的字段依然是整数类型
- 所以java实体类中和数据库中数据类型要相互转换
原理: MP提供了枚举类型处理器, 用于自动转换实体类的枚举类型

- 存储数据: 自动把枚举类型转成INT类型存入数据库
- 封装数据: 自动把数据库INT类型数据转成枚举类型保存
配置全局枚举处理器, 让枚举处理器生效
mybatis-plus:configuration:default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
给枚举类添加注解, 告诉MP要对哪个成员变量进行类型处理
@Getter
public enum UserStatus {NORMAL(1, "正常"),FROZEN(2, "冻结"),;@EnumValue // 指定写入数据库的数据private final int value;@JsonValue // 指定返回前端的数据private final String desc;UserStatus(int value, String desc) {this.value = value;this.desc = desc;}
}
- 枚举做JSON处理时, 默认会以枚举项的名字返回
- 如果想以value或者desc返回, 可以通过注解告诉SpringMVC要返回那个值


在实体类中使用枚举类型
@Data
@ApiModel(description = "用户VO实体")
public class UserVO {... ...@ApiModelProperty("使用状态(1正常 2冻结)")// private Integer status;private UserStatus status;
}
@Data
@TableName(value = "user",autoResultMap = true)
public class User {... .../*** 使用状态(1正常 2冻结)*/private UserStatus status;
}
业务代码中, 愉快的使用枚举替代魔法数值
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Override@Transactionalpublic void deductBalance(long id, Integer money) {//1,查询用户User user = getById(id);//2,校验用户状态if (user == null || user.getStatus() == UserStatus.FROZEN) {throw new RuntimeException("用户状态异常!");}//3.检查余额是否充足if (user.getBalance() < money) {throw new RuntimeException("用户余额不足!");}//4,扣减余额int remainBalance = user.getBalance() - money;lambdaUpdate().set(User::getBalance, remainBalance).set(remainBalance == 0, User::getStatus, 2).eq(User::getId, id).eq(User::getBalance, user.getBalance()) // 乐观锁.update();}
}
JSON处理器
问题说明


- user表中有一个info字段是json类型, java中没有对应的数据类型, 通常用字符串类型接收
- MuBatis可以自动进行字符串和JSON的转换
- 使用字符串接收JSON类型数据, 从数据库的操作层面是没有问题, 增删改查都是正常的
- 但是从业务层面就会出现麻烦, 比如需要取出info中的age信息, 处理起来就比较麻烦
MP提供了JSON类型处理器, 可以把java对象和数据库的JSON对象 相互转换

- SpringMVC使用的JacksonJSON处理器
- 使用JacksonTypeHandler不需要额外引用依赖
使用JSON处理器的步骤

- 使用 @TableField() 注解, 指定并开启JSON处理器
- 使用JSON数据后, 就出现了对象嵌套对象的情况, User对象嵌套UserInfo对象
- 就要开启自动结果映射 autoResultMap = true
实际操作
@Data
@NoArgsConstructor
@AllArgsConstructor(staticName = "of")
public class UserInfo {private Integer age;private String intro;private String gender;
}
- 定义PO对象封装JSON数据
@Data
@TableName(value = "user",autoResultMap = true)
public class User {... .../*** 详细信息*/@TableField(typeHandler = JacksonTypeHandler.class)// private String info;private UserInfo info;}
- 使用java对象替代String接收数据库数据
- 使用@TableField()注解开启JSON处理器
- 设置autoResultMap = true, 开启自动结果映射
- 查询结果对比


相关文章:
[MyBatis-Plus]扩展功能详解
代码生成 使用MP的步骤是非常固定的几步操作 基于插件, 可以快速的生成基础性的代码 安装插件安装完成后重启IEDA连接数据库 mp是数据库的名字?serverTimezoneUTC 是修复mysql时区, 不加会报错 生成代码 TablePrefix选项是用于去除表名的前缀, 比如根据tb_user表生成实体类U…...
循序渐进丨MogDB 5.0 远程访问 MogDB/Oracle 数据库的简便方法(使用@符号)
概述 早期的 MogDB 就提供了Postgres_fdw、Oracle_fdw、MySQL_fdw3个插件,用于远程访问 MogDB/Oracle/MySQL数据库。 旧的版本中,访问远程数据库的表,需要显式创建外部表,而在 MogDB 5.0当中,这种用法得到了简化&…...
大模型训练触达「瓶颈」,基座模型厂商还有必要坚持预训练吗?
进入2024年来,中国大模型行业从狂奔进入到了“长跑阶段”。无论是在技术侧,还是在产业侧,行业内都产生了更多新的思考。 从技术发展上看,在算力受限的情况下,中国基座模型的研发能力在全球范围内处在什么身位、如何追赶…...
media3 exoplayer 扩展解码库在这里 take it , please !
Media3 ExoPlayer 扩展解码库介绍 请注意,本文讨论的是 Media3 ExoPlayer 而不是 Google ExoPlayer2。详细参考:Media3 ExoPlayer 迁移指南 文章最后提供了已经编译好的AAR文件,直接引用即可!!! 为什么选…...
在Xshell中查看日志文件详情
学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……) 2、学会Oracle数据库入门到入土用法(创作中……) 3、手把手教你开发炫酷的vbs脚本制作(完善中……) 4、牛逼哄哄的 IDEA编程利器技巧(编写中……) 5、面经吐血整理的 面试技…...
深入理解计算机系统--计算机系统漫游
对于一段最基础代码的文件hello.c,解释程序的运行 #include <stdio.h>int main() {printf ( "Hello, world\n") ;return 0; }1.1、信息就是位上下文 源程序是由值 0 和 1 组成的位(比特)序列,8 个位被组织成一组…...
哪些指标可以用来评估精益生产现场管理和改善的效果?
在探讨如何评估精益生产现场管理和改善效果时,我们需要关注一系列关键指标,这些指标不仅反映了生产流程的效率,还体现了质量和客户满意度的提升。详细如天行健企业管理咨询公司下文所述: 1. 生产效率 每小时生产数量(…...
在 Linux 系统上安装免费杀毒软件
选择合适的免费杀毒软件 Linux 上流行的免费杀毒软件: . ClamAV:最为知名的开源免费杀毒软件,支持多种 Linux 发行版。它可以扫描病毒、恶意软件以及 Windows 系统上的威胁。 Sophos Antivirus for Linux:虽然是商业软件ÿ…...
第 7 章:Vue UI 组件库
1. PC 端常用 UI 组件库 Element UI:https://element.eleme.cnIView UI:https://www.iviewui.com 2. 移动端常用 UI 组件库 Vant:https://youzan.github.io/vantCube UI:https://didi.github.io/cube-uiMint UI:htt…...
【SQL】SQL用户管理和权限
🎄 管理用户 📢 用来管理数据库用户、控制数据库的访 问权限 ⭐ 查询用户 📢 mysql数据库中的user表中,存放了当前数据库中所有的用户和用户的权限 use mysql; select * from user; 📢 其中Host代表当前用户访问的主机, 如果为…...
STM32应用详解(5)USART串口初始化
文章目录 一、USART初始化二、代码说明1.原理图2.main函数3.USART串口初始化函数4.代码整体结构 三、USART串口初始化总结 一、USART初始化 所谓的对USART进行初始化,就是对USART固件库函数的调用,来完成串口(USART)的设置,比如设置波特率、…...
渗透实战 JS文件怎么利用
1.前言 关于JS在渗透测试中的关键作用,想必不用过多强调,在互联网上也有许多从JS中找到敏感信息从而拿下关键系统的案例。大部分师傅喜欢使用findsomething之类的浏览器插件,也有使用诸如Unexpected.information以及APIFinder之类的Burp插件…...
啥是CTF?新手如何入门CTF?
CTF是啥 CTF 是 Capture The Flag 的简称,中文咱们叫夺旗赛,其本意是西方的一种传统运动。在比赛上两军会互相争夺旗帜,当有一方的旗帜已被敌军夺取,就代表了那一方的战败。在信息安全领域的 CTF 是说,通过各种攻击手法…...
解决python多环境冲突问题
解决Python多环境冲突问题,以下是一些详细的解决方法: 1. 使用虚拟环境 虚拟环境允许你为每个项目创建独立的Python环境,每个环境可以有自己的库和依赖。常用的工具包括venv、virtualenv和pipenv。 使用 venv venv 是Python 3.3及以上版本…...
Aatrox-Bert-VITS2部署指南
一、模型介绍 【AI 剑魔 ①】在线语音合成(Bert-Vits2),将输入文字转化成暗裔剑魔亚托克斯音色的音频输出。 作者:Xz 乔希 https://space.bilibili.com/5859321 声音归属:Riot Games《英雄联盟》暗裔剑魔亚托克斯 …...
计算不停歇,百度沧海数据湖存储加速方案 2.0 设计和实践
本文整理自百度云智峰会 2024 —— 云原生论坛的同名演讲。 今天给大家介绍下百度沧海存储团队在数据湖加速方面的工作进展情况。 数据湖这个概念,从 2012 年产生到现在已经有十余年的时间,每家公司对它内涵的解读都不太一样。但是数据湖的主要存储底座…...
vue2项目 实现上边两个下拉框,下边一个输入框 输入框内显示的值为[“第一个下拉框选中值“ -- “第二个下拉框选中的值“]
效果: 思路: 采用vue中 [computed:] 派生属性的方式实现联动效果,上边两个切换时,下边的跟随变动 demo代码: <template><div><!-- 第一个下拉框 --><select v-model"firstValue"><option v-for"option in options" :key&q…...
el-radio 点击报错 Element with focus: inputAncestor with aria-hidden....
一、序言 浏览器版本影响的问题(与代码无关,可能是web或浏览器相关协议更新导致),不影响功能的使用. 翻译:元素上的Blocked aria-hidden,因为刚刚接收焦点的元素不能对辅助技术用户隐藏。避免在焦点元素或…...
集成平台,互联互通平台,企业大数据平台建设方案,技术方案(Word原件 )
企业集成平台建设方案及重点难点攻坚 基础支撑平台主要承担系统总体架构与各个应用子系统的交互,第三方系统与总体架构的交互。需要满足内部业务在该平台的基础上,实现平台对于子系统的可扩展性。基于以上分析对基础支撑平台,提出了以下要求&…...
宠物用品交易网站开发:SpringBoot技术详解
2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
