Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇

Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇_第1张图片

历史文章(文章累计490+)

《国内最全的Spring Boot系列之一》

《国内最全的Spring Boot系列之二》

《国内最全的Spring Boot系列之三》

《国内最全的Spring Boot系列之四》

《国内最全的Spring Boot系列之五》

《国内最全的Spring Boot系列之六》

SpringBoot集成MyBatis-Plus + MyBatis-Plus代码生成器[MP系列] - 第490篇

MyBatis-Plus主键生成策略[MyBatis-Plus系列] - 第491篇

MyBatis-Plus实现逻辑删除[MyBatis-Plus系列] - 492篇

悟纤:师傅,你觉得生命的本质是什么?

Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇_第2张图片

师傅:生命的本质是能量

Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇_第3张图片

师傅:喜怒哀乐都是能量

师傅:话语是能量的载体

师傅:平和的语气,合适的词语,都会安抚心灵。

Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇_第4张图片

师傅:如果话语太锋利了,就会影响对方的情绪和心情,也就是能量紊乱

Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇_第5张图片

悟纤:那两个人相处之道,不就是需要注意使用平和的语气和用合适的词语来表达了?

师傅:平和的语气能够让人听着很舒服,情绪不容易上头。

师傅:不同的词语虽然都能够表达清楚意思,但用合适的词语,听起来让人觉得舒服的词语进行表达,能够让人在心里上更加愿意去接受。

悟纤:听师傅一席话,胜读十年书。

Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇_第6张图片

导读

Hi,大家好,我是悟纤。过着爱谁谁的生活,活出不设限的人生。

通常在开发中,有这样的需求:枚举类型存入数据库存的是编码code,然而返回给前端的时候是名称name,我们每次入库的时候都要getCode()以及返回给前端的时候要getName(),很繁琐,并且字段属于那种枚举类型的可读性也不高

基于以上问题:我们会尝试着定制一些逻辑专门去处理,一般是自定义枚举转换器实现,然而mybatis-plus提供了优雅的实现方式。

一、枚举的使用场景和好处

在实际的使用当中,当某个对象或者某个属性,需要有多个可供选择的状态或者描述,例如人的性别支付的状态错误的类型等等,都可以使用枚举。

好处:

(1)可读性高, 易理解。

(2)统一参数类型,避免传参错误。

(3)线程安全,全局唯一,无法修改。

二、版本区别

Mybatis-Plus 不同的版本,通用枚举配置是不一样的,稍早一些的需要实现 IEnum 接口,并且需要在配置文件中配置 typeEnumsPackage 或者编写配置类,这难免有些复杂。

而 Mybatis-Plus 从 3.5.2 版本开始只需使用 @EnumValue 注解枚举属性,简单来说就是一个注解解决了一系列配置,本文也将讲解 @EnumValue 注解枚举属性这种方式!

三、通用枚举实战

接下来用具体的例子看一下mybatis-plus通用枚举的使用。

3.1定义枚举

3.1.1方式1:@EnumValue标注入库映射字段

使用注解@EnumValue定义存储到数据库的值:

package com.kfit.user.enums;import com.baomidou.mybatisplus.annotation.EnumValue;import com.fasterxml.jackson.annotation.JsonValue;/** * author:悟纤「公众号SpringBoot」 * date:2023/9/15 */public enum GradeEnum {    PRIMARY(1, "小学"),    SECONDORY(2, "中学"),    HIGH(3, "高中");    @EnumValue//标记数据库存的值是code    private final int code;    @JsonValue //标注该字段要开启自定义序列化返回值    private final String desc;    GradeEnum(int code, String desc) {        this.code = code;        this.desc = desc;    }}

说明:注解@JsonValue注解是开启序列化返回的值。

3.1.2方式2:枚举属性实现 IEnum 接口

实现接口IEnum定义存储到数据库的值:

package com.kfit.user.enums;import com.baomidou.mybatisplus.annotation.IEnum;import com.fasterxml.jackson.annotation.JsonValue;/** * author:悟纤「公众号SpringBoot」 * date:2023/9/15 */public enum AgeEnum implements IEnum {    ONE(1, "一岁"),    TWO(2, "二岁"),    THREE(3, "三岁");    private int value;    @JsonValue //标注该字段要开启自定义序列化返回值    private String desc;    AgeEnum(int value, String desc) {        this.value = value;        this.desc = desc;    }    @Override    public Integer getValue() {        return this.value;    }//    @Override//    public String toString() {//        return this.desc;//    }}

说明:上面两种方式定义的枚举都是可以的,使用注解@EnumValue在使用起来会更简单一些。

3.2 在实体类中使用枚举

在需要的实体类中使用上面定义的枚举,这里重新创建一个实体类:

package com.kfit.user.model;import com.kfit.user.enums.AgeEnum;import com.kfit.user.enums.GradeEnum;import lombok.Data;/** * author:悟纤「公众号SpringBoot」 * date:2023/9/15 */@Datapublic class Student {    private Long id;    private String name;    /**     * 年龄,IEnum接口的枚举处理     * 数据库字段:age INT(3)     */    private AgeEnum age;    /**     * 年级,原生枚举(带{@link com.baomidou.mybatisplus.annotation.EnumValue}):     * 数据库字段:grade INT(2)     */    private GradeEnum grade;}

3.3 定义Mapper

由于实体类是新的,定义个Mapper进行数据库的操作,如果是在原实体添加的忽略这一个步骤:

package com.kfit.user.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.kfit.user.model.Student;/** * author:悟纤「公众号SpringBoot」 * date:2023/9/15 */public interface StudentMapper extends BaseMapper {}

3.4 在表中添加对应的列

在表中添加对应的列,这里实体类是新的,需要创建一个表:

CREATE TABLE student (     `id` bigint(0) NOT NULL AUTO_INCREMENT,     `name` varchar(255) NULL,     `age` int(3) NULL,     `grade` int(2) NULL,     PRIMARY KEY (`id`));

3.5 后端测试

接下来进行简单的后端测试。

3.5.1 保存测试

先来看下保存数据的测试:

@Autowiredprivate StudentMapper studentMapper;@Testpublic void testInsert(){    Student student = new Student();    student.setName("张三");    student.setAge(AgeEnum.ONE);    student.setGrade(GradeEnum.HIGH);    studentMapper.insert(student);}

执行结果:

3.5.2 修改测试

看下修改:

@Testpublic void testUpdate(){    Student student = new Student();    student.setId(1L);    student.setName("李四");    student.setAge(AgeEnum.TWO);    student.setGrade(GradeEnum.SECONDORY);    studentMapper.updateById(student);}

运行结果:

3.5.3 查询测试

看下返回的数据情况:

@Testpublic void testSelctById(){    Student student = studentMapper.selectById(1);    System.out.println(student);}

运行结果:

Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇_第7张图片

这里显示的希望是中文的描述的话,那么需要重写AgeEnum和GradeEnum的toString()方法:

@Overridepublic String toString() {    return this.desc;}

这时候在运行一下:

Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇_第8张图片

3.6 前端测试

最后在进行一下前端测试,就是从前端请求到控制层,然后进行操作。

3.6.1 定义一个controller

首先定义controller:

package com.kfit.user.controller;import com.kfit.user.mapper.StudentMapper;import com.kfit.user.model.Student;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;/** * author:悟纤「公众号SpringBoot」 * date:2023/9/15 */@RestController@RequestMapping("/student")public class StudentController {    @Autowired    private StudentMapper studentMapper;}

3.6.2 查询测试

进行查询测试:

@RequestMapping("/select")public Student selectStudent(){    return studentMapper.selectById(1);}

请求地址:

http://127.0.0.1:8080/student/select

请求结果:

Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇_第9张图片

结果显示很正常,如果显示的不是中文的话,那么看看有没有在属性上添加了@JsonValue的注解,如果使用的是其它的JSON框架的话,那么对应的是什么注解。

3.6.3 保存测试

编写保存测试代码:

@RequestMapping("/save")public int save(@RequestBody Student student){    return studentMapper.insert(student);}

请求地址:

http://127.0.0.1:8080/student/save

请求体:

{    "name": "wuqian",    "age": "二岁",    "grade": "高中"}

请求结果:

除了 "age": "二岁","age": 1 也能达到相同的效果,需要注意的是:"age": 1 对枚举类的要求苛刻,需要保证枚举数字从0开始并按顺序排列,因为它是按顺序取枚举的。

也就是说:

设置age=0,那么对应的是ONE(1, "一岁");

设置age=1,那么对应的是TWO(2, "二岁");

如果要使用这种方式,最好是code从0开始,并且是顺序排列的,不然可能会出现莫名其妙的错误。

3.6.4 保存测试2

​上面保存是使用的JSON的方式,如果使用get请求地址这样的请求呢?

@RequestMapping("/save1")public int save1(Student student){    return studentMapper.insert(student);}

请求地址:

http://127.0.0.1:8080/student/save1?name=wuqian&age=二岁

请求报错:

Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errorsField error in object 'student' on field 'age': rejected value [二岁]; codes [typeMismatch.student.age,typeMismatch.age,typeMismatch.com.kfit.user.enums.AgeEnum,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [student.age,age]; arguments []; default message [age]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.kfit.user.enums.AgeEnum' for property 'age'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [com.kfit.user.enums.AgeEnum] for value [二岁]; nested exception is java.lang.IllegalArgumentException: No enum constant com.kfit.user.enums.AgeEnum.二岁]]

所以这种方式不能够这样子请求,可以这样子请求:

http://127.0.0.1:8080/student/save1?name=wuqian&age=ONE

请求结果:

那能不能传递value值呢 ?这个就需要重写StringToEnumConverterFactory的,可以自行去了解一下。

小结

本节介绍了MP的通用枚举功能,对于本文的知识重点总结一下:

(1)通用枚举定义的两种方式:其一使用注解@EnumValue;其二实现接口IEnum。

(2)后端测试想要返回对应的描述,可以重写toString()方法。

(3)前端测试想要返回对应的描述,可以添加注解@JsonValue。

(4)如果请求方式是json的方式,那么可以直接进行转换。

(5)如果请求方式是x-www-form-urlencoded,那么要使用name的方式,否则要重写类StringToEnumConverterFactory。

1000道互联网Java工程师面试题

Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇_第10张图片

包括了:MyBatis、ZK、Dubbo、EL、Redis、MySQL、并发编程、Java面试、Spring、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题(共 485 页,32W字)

领取方式:关注公众号「SpringBoot」,回复[面试资料]

点赞、转发、评论,伸出你的双手666…


i 你就是你,不一样的小蚂蚁!

你可能感兴趣的:(MyBatis-Plus系列,spring,boot,mybatis,mybatis-plus)