[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的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...
前端开发者常用网站
Can I use网站:一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use:Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站:MDN JavaScript权威网站:JavaScript | MDN...
