MyBatis-Plus 实战教程三 拓展插件

news2024/7/4 5:38:30

文章目录

  • 扩展功能
    • 代码生成
      • 安装插件
      • 使用
    • 静态工具
    • 逻辑删除
    • 通用枚举
      • 定义枚举
      • 配置枚举处理器
      • 测试
    • JSON类型处理器
      • 定义实体
      • 使用类型处理器
    • 仓库地址

扩展功能

代码生成

在使用MybatisPlus以后,基础的Mapper、Service、PO代码相对固定,重复编写也比较麻烦。因此MybatisPlus官方提供了代码生成器根据数据库表结构生成PO、Mapper、Service等相关代码。只不过代码生成器同样要编码使用,也很麻烦。
这里推荐大家使用一款MybatisPlus的插件,它可以基于图形化界面完成MybatisPlus的代码生成,非常简单。

安装插件

在Idea的plugins市场中搜索并安装MyBatisPlus插件:
请添加图片描述

然后重启你的Idea即可使用。

使用

刚好数据库中还有一张address表尚未生成对应的实体和mapper等基础代码。我们利用插件生成一下。
首先需要配置数据库地址,在Idea顶部菜单中,找到other,选择Config Database:
请添加图片描述

在弹出的窗口中填写数据库连接的基本信息:
请添加图片描述

点击OK保存。
然后再次点击Idea顶部菜单中的other,然后选择Code Generator:
请添加图片描述

在弹出的表单中填写信息:
请添加图片描述

最终,代码自动生成到指定的位置了:

静态工具

有的时候Service之间也会相互调用,为了避免出现循环依赖问题,MybatisPlus提供一个静态工具类:Db,其中的一些静态方法与IService中方法签名基本一致,也可以帮助我们实现CRUD功能:

示例:


@Test
void testDbGet() {
    User user = Db.getById(1L, User.class);
    System.out.println(user);
}

@Test
void testDbList() {
    // 利用Db实现复杂条件查询
    List<User> list = Db.lambdaQuery(User.class)
            .like(User::getUsername, "o")
            .ge(User::getBalance, 1000)
            .list();
    list.forEach(System.out::println);
}

@Test
void testDbUpdate() {
    Db.lambdaUpdate(User.class)
            .set(User::getBalance, 2000)
            .eq(User::getUsername, "Rose");
}

需求:改造根据id用户查询的接口,查询用户的同时返回用户收货地址列表
首先,我们要添加一个收货地址的VO对象:

package com.onenewcode.mpdemo.domain.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@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;
}

然后,改造原来的UserVO,添加一个地址属性:

接下来,修改UserController中根据id查询用户的业务接口:

@GetMapping("/{id}")
@ApiOperation("根据id查询用户")
public UserVO queryUserById(@PathVariable("id") Long userId){
    // 基于自定义service方法查询
    return userService.queryUserAndAddressById(userId);
}

由于查询业务复杂,所以要在service层来实现。首先在IUserService中定义方法:

package com.onenewcode.mpdemo.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.onenewcode.mpdemo.domain.po.User;
import com.onenewcode.mpdemo.domain.vo.UserVO;

public interface UserService extends IService<User> {
    void deduct(Long id, Integer money);

    UserVO queryUserAndAddressById(Long userId);
}


然后,在UserServiceImpl中实现该方法:

@Override
public UserVO queryUserAndAddressById(Long userId) {
    // 1.查询用户
    User user = getById(userId);
    if (user == null) {
        return null;
    }
    // 2.查询收货地址
    List<Address> addresses = Db.lambdaQuery(Address.class)
            .eq(Address::getUserId, userId)
            .list();
    // 3.处理vo
    UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
    userVO.setAddresses(BeanUtil.copyToList(addresses, AddressVO.class));
    return userVO;
}

在查询地址时,我们采用了Db的静态方法,因此避免了注入AddressService,减少了循环依赖的风险。

逻辑删除

对于一些比较重要的数据,我们往往会采用逻辑删除的方案,即:

  • 在表中添加一个字段标记数据是否被删除
  • 当删除数据时把标记置为true
  • 查询时过滤掉标记为true的数据
    一旦采用了逻辑删除,所有的查询和删除逻辑都要跟着变化,非常麻烦。

为了解决这个问题,MybatisPlus就添加了对逻辑删除的支持。
注意,只有MybatisPlus生成的SQL语句才支持自动的逻辑删除,自定义SQL需要自己手动处理逻辑删除。

例如,我们给address表添加一个逻辑删除字段:

alter table address add deleted bit default b'0' null comment '逻辑删除';

然后给Address实体添加deleted字段:
请添加图片描述

接下来,我们要在application.yml中配置逻辑删除字段:

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

测试:
首先,我们执行一个删除操作:

@Test
void testDeleteByLogic() {
    // 删除方法与以前没有区别
    addressService.removeById(59L);
}

方法与普通删除一模一样,但是底层的SQL逻辑变了:
请添加图片描述

查询一下试试:

@Test
void testQuery() {
    List<Address> list = addressService.list();
    list.forEach(System.out::println);
}

会发现id为59的确实没有查询出来,而且SQL中也对逻辑删除字段做了判断:

综上, 开启了逻辑删除功能以后,我们就可以像普通删除一样做CRUD,基本不用考虑代码逻辑问题。还是非常方便的。
注意:
逻辑删除本身也有自己的问题,比如:

  • 会导致数据库表垃圾数据越来越多,从而影响查询效率
  • SQL中全都需要对逻辑删除字段做判断,影响查询效率
    因此,我不太推荐采用逻辑删除功能,如果数据不能删除,可以采用把数据迁移到其它表的办法。

通用枚举

User类中有一个用户状态字段:
请添加图片描述

像这种字段我们一般会定义一个枚举,做业务判断的时候就可以直接基于枚举做比较。但是我们数据库采用的是int类型,对应的PO也是Integer。因此业务操作时必须手动把枚举与Integer转换,非常麻烦。
因此,MybatisPlus提供了一个处理枚举的类型转换器,可以帮我们把枚举类型与数据库类型自动转换。

定义枚举

我们定义一个用户状态的枚举:
请添加图片描述

代码如下:

package com.onenewcode.mpdemo.enums;

import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.Getter;

@Getter
public enum UserStatus {
    NORMAL(1, "正常"),
    FREEZE(2, "冻结")
    ;
    private final int value;
    private final String desc;

    UserStatus(int value, String desc) {
        this.value = value;
        this.desc = desc;
    }
}

然后把User类中的status字段改为UserStatus 类型:
请添加图片描述

要让MybatisPlus处理枚举与数据库类型自动转换,我们必须告诉MybatisPlus,枚举中的哪个字段的值作为数据库值。
MybatisPlus提供了@EnumValue注解来标记枚举属性:
请添加图片描述

配置枚举处理器

在application.yaml文件中添加配置:

mybatis-plus:
  configuration:
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler

测试

@Test
void testService() {
    List<User> list = userService.list();
    list.forEach(System.out::println);
}

最终,查询出的User类的status字段会是枚举类型

JSON类型处理器

数据库的user表中有一个info字段,是JSON类型
格式像这样:
{“age”: 20, “intro”: “佛系青年”, “gender”: “male”}
而目前User实体类中却是String类型:
这样一来,我们要读取info中的属性时就非常不方便。如果要方便获取,info的类型最好是一个Map或者实体类。

而一旦我们把info改为对象类型,就需要在写入数据库时手动转为String,再读取数据库时,手动转换为对象,这会非常麻烦。

因此MybatisPlus提供了很多特殊类型字段的类型处理器,解决特殊字段类型与数据库类型转换的问题。例如处理JSON就可以使用JacksonTypeHandler处理器。

定义实体

首先,我们定义一个单独实体类来与info字段的属性匹配:
代码如下:

package com.onenewcode.mpdemo.domain.po;

import lombok.Data;

@Data
public class UserInfo {
    private Integer age;
    private String intro;
    private String gender;
}

使用类型处理器

接下来,将User类的info字段修改为UserInfo类型,并声明类型处理器:
请添加图片描述

同时,为了让页面返回的结果也以对象格式返回,我们要修改UserVO中的info字段:
请添加图片描述

仓库地址

https://github.com/onenewcode/mp-demo.git

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

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

相关文章

鸿蒙开发第一步-入门

本人安卓开发小趴菜一枚&#xff0c;在现公司做中控产品&#xff0c;目前通过 Java,Kotlin开发&#xff0c;但是随着后面可能会用到华为产品(后续华为可能不支持安卓)做中控设备&#xff0c;所以在领导的建议下&#xff0c;入手鸿蒙开发。 先说下中控产品吧&#xff0c;以pad开…

线扫相机DALSA-相机平场矫正详细步骤

在相机视野下铺放白色亚克力板或纯白纸&#xff0c;采集图像。打开曲线图。 选择 Line Profile 模式。调节好相应所需的曝光时间、光源、增益和镜头光圈&#xff0c;让白平衡纸显示出来的灰度值大概在 150-200 左右。 在Calibration Algorithm 中将显示的数值设置好。 先暗场…

NodeJS回调地狱及Promise优化

NodeJS中有很多异步API&#xff0c;比如常见的fs模块的readFile方法。虽然有同步的版本readFileSync, 但是其性能肯定不如前者。所以这里从异步异步版本readFile说起: const fs require(fs);fs.readFile(./a.txt, utf-8, function(error, data) {if (!error) {console.log(a.…

目标检测理论知识

目标检测 1.基本概念 目标检测&#xff08;Object Detection&#xff09;的任务是找出图像中所有感兴趣的目标&#xff08;物体&#xff09;&#xff0c;确定它们的类别和位置&#xff0c;是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态&#xff0c;…

【Linux】深入理解系统文件操作(1w字超详解)

1.系统下的文件操作&#xff1a; ❓是不是只有C\C有文件操作呢&#xff1f;&#x1f4a1;Python、Java、PHP、go也有&#xff0c;他们的文件操作的方法是不一样的啊 1.1对于文件操作的思考&#xff1a; 我们之前就说过了&#xff1a;文件内容属性 针对文件的操作就变成了对…

AI:43-基于深度学习的昆虫图像识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌本专栏包含以下学习方向: 机器学习、深度学…

AI:42-基于机器学习方法下以沙发为例的家具风格识别技术研究

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌本专栏包含以下学习方向: 机器学习、深度学…

【AD9361 数字接口CMOS LVDSSPI】C 并行数据 LVDS <续>

续【AD9361 数字接口CMOS &LVDS&SPI】C 并行数据之LVDS 不同于CMOS的传输方式&#xff0c;lvds只能工作在双端口全双工模式下。 一、 双端口全双工模式 &#xff08;LVDS&#xff09;代称 DFL DUAL PORT FULL DUPLEX MODE DFL 模式通过写入SPI寄存器实现。在此模式下…

html+js+css实现一个圆形滑块

htmljscss实现一个圆形滑块&#xff0c;可以拖动&#xff0c;可以点击&#xff0c;先看效果再讲原理&#xff0c;最后附上源码&#xff1a; 产品经理设计了这样一个需求&#xff0c;通过拖动圆形滑块实现时间的设置功能&#xff0c;虽然看着有点复杂&#xff0c;但是确实有点复…

vite+vue3实现 tomcat 的本地部署

背景&#xff1a; 很多开发小伙伴在本地开发完前端项目后&#xff0c;碍于服务端环境配置麻烦&#xff0c;想先试试在本地部署&#xff0c;已开发好的前端项目&#xff0c;由于很多文章都是文字性描述&#xff0c;不太直观&#xff0c;为了给大多数新手提供一个教程&#xff0c…

Agent 应用于提示工程

如果Agent模仿了人类在现实世界中的操作方式&#xff0c;那么&#xff0c;能否应用于提示工程即Prompt Engingeering 呢&#xff1f; 从LLM到Prompt Engineering 大型语言模型(LLM)是一种基于Transformer的模型&#xff0c;已经在一个巨大的语料库或文本数据集上进行了训练&…

ubuntu 22.04 源码安装 apollo 8.0

对于其他的关于GPU的安装包需求&#xff0c;这里不再列出&#xff0c;因为我之前安装过&#xff0c;偷个懒就不写了&#xff0c;哈哈哈哈1, 安装docker 安装docker命令(这里的安装命令都是在docker官网,还有安装包)&#xff1a; 1&#xff0c; 设置docker的apt仓库 # Add Do…

论坛搭建.

目录 一.配置软件仓库 二.安装http php miriadb 三.配置数据库 一.配置软件仓库 1.进入仓库目录 cd /etc/yum.repos.d 2.创建仓库文件 vim local.repo 3.在 local.repo中写入:(粘贴的时候注意位置) [biaoshi] 仓库标识符 namemiaoshu …

【中国知名企业高管团队】系列52:魅族手机

华研荟中国手机企业的高管团队系列文章&#xff0c;今天介绍一个特别的存在——魅族。华研荟一度以为这个品牌被雪藏或者不再发展了&#xff0c;昨天在商场看到竟然开起了线下专卖店&#xff0c;尽管店里面门可罗雀&#xff0c;产品类别和数量也有限&#xff0c;但是仍然觉得有…

数据库连接问题 1251

Navicat连接本地数据库时出现的问题 解决办法 &#xff1a; 打开 输入密码 然后输入 ALTER USER ‘root’‘localhost’ IDENTIFIED WITH mysql_native_password BY ‘123456’; FLUSH PRIVILEGES;

pointNet复现、论文和代码研读

文章目录 论文复现论文研读1.动机2.模型结构![在这里插入图片描述](https://img-blog.csdnimg.cn/286bc0bfc06846f690adde4979366977.png)3.实验效果4.总结 代码研读模型什么时候保存&#xff0c;保存到哪里&#xff1f;模型训练的数据集&#xff1f;为什么是在CPU上运行的&…

如何在不污染代码的情况下给大R玩家定制特殊服务

点击上方亿元程序员关注和★星标 引言 大家好&#xff0c;我是亿元程序员&#xff0c;一位有着8年游戏行业经验的主程。 本系列是《和8年游戏主程一起学习设计模式》&#xff0c;让糟糕的代码在潜移默化中升华&#xff0c;欢迎大家关注分享收藏订阅。 为了在不污染代码的情况…

39基于matlab的全局路径规划算法中的快速扩展随机树RRT路径规划算法及其改进方法

基于matlab的全局路径规划算法中的快速扩展随机树RRT路径规划算法及其改进方法&#xff0c;RRT Star、RRT_Conncet是一种具有状态约束的非线性系统生成开环轨迹的技术&#xff0c;相比于其他算法可以轻松处理障碍物的问题。程序中的各参数已进行详细说明&#xff0c;起点坐标&a…

[ASP]青辰网络考试管理系统NES X3.5

源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88452220 青辰智能网络考试管理系统NES采用功能强大、高效灵活的B/S 架构模式&#xff0c;先进的HTML5技术作为前端开发&#xff0c;用户可通过PC、手机、平板等终端进行访问。具有高度的可扩展性&#x…

Mac 4款必备精品软件

一、Downie Downie 是一款万能下载器&#xff0c;它已经出到第 4 代了&#xff0c;它可以作为你的浏览器插件使用&#xff0c;Downie 让你几乎能够下载在网页上的一切内容。比如你在网站上看到一个很有意思的视频&#xff0c;看一遍不够过瘾&#xff0c;想要下载下来反复观看。…