重生之我在暑假学习微服务第二天《MybatisPlus-下篇》

发布于:2025-07-28 ⋅ 阅读:(21) ⋅ 点赞:(0)

本系列参考黑马程序员微服务课程,有兴趣的可以去查看相关视频,本系列内容采用渐进式方式讲解微服务核心概念与实践方法,每日更新确保知识点的连贯性。通过系统化学习路径帮助开发者掌握分布式系统构建的关键技术。读者可通过平台订阅功能获取最新章节推送,及时了解服务拆分、容器化部署、服务网格等前沿技术动态。
 

特别声明:本篇文章对应黑马程序员微服务课程P11-P20 

目录

前言 

一、安装插件

MyBatis-Plus 插件的意义

1.找到idea中的插件

2.在插件市场中搜索MyBatisPlus插件

3. 配置所需信息

4. 配置成自己的

5.接下来就可以直接使用了

6.开始生成

二、DB静态工具

测试一:改造根据id查询

1.先导入AddressVO

 2.在UserVO中添加AddressVO字段​编辑

3.开始修改代码

4.用Apifox测试

测试二:改造根据id批量查询 

1.还是先改造Controll层代码

 2.实现方法

3.解释方法

(1)查询用户基本信息

(2)查询用户地址信息

(3)地址信息处理和分组

(4)封装最终结果

4、测试结果

三、逻辑删除

1.先配置逻辑删除相关语句

2.新建一个测试

 3.测试结果

4.查看数据库表结构 

四、处理器

MyBatis-Plus 中的处理器

元对象处理器(MetaObjectHandler)

分页插件处理器(PaginationInnerInterceptor)

动态表名处理器(DynamicTableNameInnerInterceptor)

乐观锁处理器(OptimisticLockerInnerInterceptor)

SQL 注入处理器(AbstractSqlInjector)

性能分析处理器(PerformanceInterceptor)

注意事项

1、枚举处理器

(1)新建一个枚举文件来存放枚举类型

(2)配置枚举处理器​编辑

 (3)修改实体类

 (4)修改代码

(5)测试 

2、JSON处理器

五、分页插件

1、先配置实体类

2、测试

 六、分页查询案例

1、先创建实体类 

​编辑 2、用户继承该实体类

3、定义返回结果

 4、开始测试

mybatisplus篇结尾

总结与展望


 

前言 

窗外的蝉鸣又起时,VON 的笔记本已经写满半本。晨光漫过屏幕,照亮他眼下淡淡的青黑 —— 凌晨三点才在代码调试成功的提示音里睡去,七点却被生物钟拽醒。​

他点开《MyBatisPlus 基础入门》的第三章,指尖在手机屏幕上飞快滑动。@TableName 注解那页还粘着昨晚吃泡面时溅的汤渍,此刻倒成了醒目的标记。"原来实体类和数据库表名不一致时,加这个注解就能映射..." 他对着示例敲下代码,看着控制台弹出的 "查询成功" 提示,突然想起前世写的那堆冗长 SQL,耳根发烫。​

条件构造器是块硬骨头。QueryWrapper 的嵌套查询让他卡了整整两小时,报错信息像密集的蚂蚁爬满屏幕。窗外的蝉鸣又开始聒噪,他抓着头发盯着那句 "LambdaQueryWrapper lqw = new LambdaQueryWrapper<>()",忽然想起班长发的资料里提过" 链式调用更直观 "。指尖在键盘上重新跳跃,当根据年龄和性别筛选出的用户列表整齐排列在控制台时,他狠狠捶了下桌面,震得马克杯里的速溶咖啡泛起涟漪。​

自定义 SQL 部分倒意外顺利。或许是前世被冗余代码折磨出的本能,当他在 XML 文件里写出带条件判断的动态 SQL 时,竟有种莫名的熟悉感。阳光穿过纱窗在代码上投下格子影,他忽然发现,那些曾经让他望而生畏的尖括号,此刻正像列队的士兵般温顺。​

下午三点,Service 接口的批量新增测试成功。看着一百条用户数据瞬间写入数据库,VON 摸出手机翻到游戏群,前世此刻他本该在喊 "开团"。群里依旧热闹,他却平静地点了退出。​

最后一行代码运行结束时,晚霞正把天空染成橘红色。VON 合上笔记本,发现封面上的倒影里,自己的眼睛比昨天更亮了些。蝉鸣渐歇的暮色里,他仿佛听见未来的自己敲代码的声音,清脆又笃定。

至此,MybatisPlus篇完结!!!

一、安装插件

MyBatis-Plus 插件的意义

MyBatis-Plus(简称 MP)是基于 MyBatis 的增强工具插件,旨在简化开发、提升效率。其核心意义在于为 MyBatis 提供更便捷的功能扩展,同时保持与原生 MyBatis 的无缝兼容。

1.找到idea中的插件

2.在插件市场中搜索MyBatisPlus插件

3. 配置所需信息

4. 配置成自己的

 

这里测试的时候报错了,问了下豆包,说是时区问题。

The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support. 

修改方案:

这样就表示成功了 

5.接下来就可以直接使用了

可以看到这里出现的表正是我们数据库中的表

6.开始生成

配置成我这样就可以

 出现这个标志就成功了

这些全都是这个插件生成的代码 

 

二、DB静态工具

DB静态工具是指用于数据库设计、分析、优化的非运行时工具,通常在数据库开发或维护阶段使用。这类工具不直接与运行中的数据库交互,而是通过静态分析数据结构、SQL脚本或元数据来提供支持。

测试一:改造根据id查询

1.先导入AddressVO

 2.在UserVO中添加AddressVO字段

3.开始修改代码

 原UserController

 现UserController

 实现方法

4.用Apifox测试

测试成功

测试二:改造根据id批量查询 

1.还是先改造Controll层代码

 2.实现方法

@Override
    public List<UserVO> queryUsersAndAddressByIds(List<Long> ids) {
        //1.查询用户
        List<User> users = listByIds(ids);
        if(CollUtil.isEmpty(users)){
            return Collections.emptyList();
        }
        //2.查询地址
        //获取id集合
        List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
        List<Address> address = Db.lambdaQuery(Address.class)
                .in(Address::getUserId, userIds)
                .list();
        List<AddressVO> addressVOList = BeanUtil.copyToList(address, AddressVO.class);
        Map<Long, List<AddressVO>> addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));

        //3.封装VO
        List<UserVO> userVOList = BeanUtil.copyToList(users, UserVO.class);
        userVOList.forEach(userVO -> {
            userVO.setAddress(addressMap.get(userVO.getId()));
        });
        return userVOList;
    }

3.解释方法

这个方法有点复杂了,这里解释一下相关步骤

(1)查询用户基本信息
List<User> users = listByIds(ids);
if(CollUtil.isEmpty(users)){
    return Collections.emptyList();
}
  • 使用 listByIds(ids) 方法根据ID列表批量查询用户
  • 如果查询结果为空,则返回空列表
(2)查询用户地址信息
List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
List<Address> address = Db.lambdaQuery(Address.class)
        .in(Address::getUserId, userIds)
        .list();
  • 从查询到的用户列表中提取所有用户ID
  • 使用 Db.lambdaQuery() 构造查询条件,通过 in 条件批量查询这些用户的所有地址信息
(3)地址信息处理和分组
List<AddressVO> addressVOList = BeanUtil.copyToList(address, AddressVO.class);
Map<Long, List<AddressVO>> addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
  •  使用 BeanUtil.copyToList() 将 Address 对象列表转换为 AddressVO 对象列表
  • 使用 Collectors.groupingBy() 按用户ID对地址进行分组,形成 Map<用户ID, 地址列表> 的结构
(4)封装最终结果
List<UserVO> userVOList = BeanUtil.copyToList(users, UserVO.class);
userVOList.forEach(userVO -> {
    userVO.setAddress(addressMap.get(userVO.getId()));
});
return userVOList;
  • 将用户信息转换为 UserVO 对象列表
  • 遍历每个 UserVO 对象,从 addressMap 中获取对应用户ID的地址列表并设置到 UserVO 中
  • 返回封装好的用户VO列表

4、测试结果

可以看到可以正常查询

三、逻辑删除

逻辑删除是一种数据管理方式,通过标记记录的状态而非物理删除数据。通常通过添加一个字段(如 is_deletedstatus)标识记录是否“已删除”,实际数据仍保留在数据库中。

1.先配置逻辑删除相关语句

2.新建一个测试

 3.测试结果

4.查看数据库表结构 

 不难看出这里的deleted字段变成了true,说明已经被逻辑删除掉了

四、处理器

MyBatis-Plus 中的处理器

MyBatis-Plus 提供了多种处理器(Handler)用于扩展或定制框架行为,主要分为以下几类:

元对象处理器(MetaObjectHandler)

用于自动填充公共字段(如创建时间、更新时间、操作人等)。通过实现 MetaObjectHandler 接口并重写以下方法:

@Override
public void insertFill(MetaObject metaObject) {
    // 插入时自动填充字段
    this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
}

@Override
public void updateFill(MetaObject metaObject) {
    // 更新时自动填充字段
    this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}

需通过 @Component 注解注册为 Spring Bean。

分页插件处理器(PaginationInnerInterceptor)

用于实现物理分页功能,需通过配置类启用:

@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

支持多种数据库方言,自动识别并转换分页语句。

动态表名处理器(DynamicTableNameInnerInterceptor)

用于动态替换表名,适用于分表场景:

DynamicTableNameInnerInterceptor interceptor = new DynamicTableNameInnerInterceptor();
interceptor.setTableNameHandler((sql, tableName) -> {
    return "实际表名逻辑";
});

乐观锁处理器(OptimisticLockerInnerInterceptor)

通过版本号实现乐观锁,需在实体类字段添加 @Version 注解:

@Version
private Integer version;

配置拦截器后,更新操作会自动检测版本号一致性。

SQL 注入处理器(AbstractSqlInjector)

用于自定义全局 SQL 方法,需继承 AbstractSqlInjector 并实现 inspectInject 方法:

public class CustomSqlInjector extends AbstractSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList() {
        return Stream.of(new InsertBatchSomeColumn()).collect(Collectors.toList());
    }
}

性能分析处理器(PerformanceInterceptor)

已废弃,推荐使用第三方监控工具(如 P6Spy)替代。

注意事项
  • 处理器需通过 MybatisPlusInterceptoraddInnerInterceptor 方法添加
  • 多个拦截器按添加顺序执行
  • 部分处理器需配合注解或实体类字段使用

可以看到处理器的类型十分丰富,这里给大家详解一下以下两个处理器的使用

1、枚举处理器

(1)新建一个枚举文件来存放枚举类型

(2)配置枚举处理器

 (3)修改实体类

 (4)修改代码

将出现的状态码都修改一下

UserVO实体类也要改一下 

(5)测试 

测试一下观察返回值 

这里返回值变成了枚举类型的,这可不是我们想要的结果

 解决方案也很简单,只需要添加这么一个注解即可

 

可以看到这是展现的就是我们预期的效果了 

2、JSON处理器

JSON 处理器是一种用于解析、生成、转换和操作 JSON(JavaScript Object Notation)数据的工具或库。其核心功能包括:

  • 解析:将 JSON 字符串转换为编程语言中的数据结构(如对象、字典、数组等)。
  • 序列化:将内存中的数据结构转换为 JSON 字符串。
  • 查询与修改:支持路径查询(如 JSONPath)、节点增删改查等操作。
  • 验证:检查 JSON 数据是否符合特定模式(如 JSON Schema)。
  • 格式化:美化或压缩 JSON 字符串以提高可读性或传输效率。

先创建实体类

注:要和表中数据保持一致 

 这里的字段也要加一下注解

 

添加这一字段

这里也要修改一下,凡是涉及到的都要修改

 就像这样的,都要修改为上面那种

 UserVO实体类也要改

改为UserInfo

测试

不难看出这里的info字段变成了json格式

五、分页插件

分页插件是一种用于将大量数据分割成多个页面的工具,通常用于网页或应用程序中,以提高数据加载效率和用户体验。它允许用户通过导航按钮(如上一页、下一页、页码跳转)浏览不同页面的数据,避免一次性加载全部内容。

1、先配置实体类

2、测试

注意一下这里的page包,别导入错了

这里当时添加数据后忘记删除了

可以看到我们设置的每页2条数据,5条数据正好三页。

 六、分页查询案例

1、先创建实体类 

 2、用户继承该实体类

3、定义返回结果

 

 4、开始测试

service层代码

@Override
    public PageDTO<UserVO> queryUsersPage(UserQuery query) {
        String name = query.getName();
        Integer status = query.getStatus();

        Page<User> page = new Page<>(query.getPageNo(), query.getPageSize());
        if(StrUtil.isNotBlank(query.getSortBy())){
            //不为空
            page.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));
        }else{
            page.addOrder(new OrderItem("update_time", false));
        }

        Page<User> p = lambdaQuery().like(name != null, User::getUsername, name).eq(status != null, User::getStatus, status).page( page);
        //封装
        PageDTO<UserVO> dto = new PageDTO<>();
        dto.setTotal(p.getTotal());
        dto.setPages(p.getPages());
        List<User> records = p.getRecords();
        if(records != null){
            List<UserVO> vos = BeanUtil.copyToList(records, UserVO.class);
            dto.setList(vos);
        }
        return dto;
    }

测试结果 

mybatisplus篇结尾

MyBatis-Plus作为一款强大的MyBatis增强工具,极大简化了开发者的数据库操作流程,提升了开发效率。通过自动生成代码、内置通用Mapper和Service,开发者可以专注于业务逻辑的实现,减少重复性工作。

MyBatis-Plus支持多种数据库,并提供丰富的查询条件构造器,满足复杂查询需求。其强大的性能优化和灵活的插件机制,使得数据库操作更加高效和安全。无论是新项目搭建还是旧项目改造,MyBatis-Plus都能提供便捷的解决方案。

在实际开发中,合理使用MyBatis-Plus的功能,可以显著提升开发效率和代码质量。结合Spring Boot等框架,能够快速构建稳定可靠的企业级应用。持续关注MyBatis-Plus的更新和社区动态,能够更好地利用其最新特性。

总结与展望

MyBatis-Plus的未来发展潜力巨大,随着技术的不断进步,更多实用功能将被引入。开发者应持续学习和实践,充分利用MyBatis-Plus的优势,构建高效、可维护的应用程序。


网站公告

今日签到

点亮在社区的每一天
去签到