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

历史文章(文章累计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篇

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

师傅:生命的本质是能量

师傅:喜怒哀乐都是能量

师傅:话语是能量的载体

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

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

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

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

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

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

导读

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<Integer> {    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<Student> {}

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

运行结果:

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

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

这时候在运行一下:

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

请求结果:

结果显示很正常,如果显示的不是中文的话,那么看看有没有在属性上添加了@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 errors<EOL>Field 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、ZK、Dubbo、EL、Redis、MySQL、并发编程、Java面试、Spring、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题(共 485 页,32W字)

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

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


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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AS/400-对象管理-01

对象管理 对象对象构图 AS/400中的库命令Display Library List (DSPLIBL)Create Library (CRTLIB)Display library (DSPLIB)Edit Library List (EDTLIBL) Source physical file 物理文件创建物理文件的命令 &#xff1a; CRTSRCPF 物理文件查看所有物理文件的源文件创建源文件…

2023年中国冷风机分类、销量及市场规模分析[图]

冷风机通常是指一种设备&#xff0c;用于通过冷却空气来调节室内或工业环境的温度。这些设备通过循环空气并通过冷却元件&#xff08;如冷却盘或冷凝器&#xff09;来降低空气的温度&#xff0c;从而实现温度控制。冷风机在家庭、商业和工业领域都有广泛的应用&#xff0c;可以…

geoserver去除tif影像黑色的背景的方法

geoserver加载某些tif文件的时候,tif文件本身有黑色的背景,怎么去掉呢? 只要在geoserver中设置就行。 处理方法: 1.新建数据源时要选择ImageMosaic数据源 2,设置"Output Transparent Color" 设置"Output Transparent Color"为黑色(000000),在…

Postgresql在jdbc处理bit字段的解决方案

问题&#xff1a; bit如果长度为1&#xff0c;则会默认为布尔型&#xff08;1-true 0-false&#xff09;&#xff1b; bit如果长度大于1&#xff0c;则会默认为bit类型&#xff0c;但是代码中以前常用的两种set方式&#xff0c;会报错 第一种方式&#xff1a; ps.setObject(i1,…

【工具】FreePic2PDF+PdgCntEditor|PDF批量添加书签(Windows)

这俩软件都不大&#xff0c;比较便携。 FreePic2PDF&#xff1a; 我下载的来源&#xff1a;https://www.52pojie.cn/thread-1317140-1-1.html&#xff08;包含下载链接https://www.lanzoui.com/it4x6j4hbvc&#xff09;下载的结果&#xff1a;https://pan.baidu.com/s/1r8n5G42…

win 下安装 nvm 的使用与配置

nvm 全名 node.js version management&#xff0c;是一个 nodejs 的版本管理工具。通过它可以安装和切换不同版本的 nodejs。 注&#xff1a;如果已经安装了 nodejs 需先卸载后再安装 nvm 为了确保 nodejs 已彻底删除&#xff0c;可以看看安装目录中是否有 node 文件夹&#x…

解密人工智能:决策树 | 随机森林 | 朴素贝叶斯

文章目录 一、机器学习算法简介1.1 机器学习算法包含的两个步骤1.2 机器学习算法的分类 二、决策树2.1 优点2.2 缺点 三、随机森林四、Naive Bayes&#xff08;朴素贝叶斯&#xff09;五、结语 一、机器学习算法简介 机器学习算法是一种基于数据和经验的算法&#xff0c;通过对…

js的小题

//闭包实例代码 function fn1() {let a 1;function fn2() {a;console.log(a);}console.log(a,a) } fn1(); 执行结果: 1 a 现在思考怎么调用里面的fn2函数呢? 答案是: //闭包实例代码 function fn1() {let a 1;function fn2() {a;console.log(a);}console.log(a,a)return f…

安卓核心板_天玑700、天玑720、天玑900_5G模块规格参数

5G安卓核心板是采用新一代蜂窝移动通信技术的重要设备。它支持万物互联、生活云端化和智能交互的特性。5G技术使得各类智能硬件始终处于联网状态&#xff0c;而物联网则成为5G发展的主要动力。物联网通过传感器、无线网络和射频识别等技术&#xff0c;实现了物体之间的互联。而…

正点原子嵌入式linux驱动开发——Linux RTC驱动

RTC也就是实时时钟&#xff0c;用于记录当前系统时间&#xff0c;对于Linux系统而言时间是非常重要的&#xff0c;就和使用Windows电脑或手机查看时间一样&#xff0c;在使用Linux设备的时候也需要查看时间。本章就来学习一下如何编写Linux下的RTC驱动程序。 Linux内核RTC驱动…

算法笔记【8】-合并排序算法

文章目录 一、前言二、合并排序算法基本原理三、实现步骤四、优缺点分析 一、前言 合并排序算法通过采用分治策略和递归思想&#xff0c;实现了高效、稳定的排序功能。本文将深入探讨合并排序算法的原理、实现步骤&#xff0c;并讨论其优缺点。 二、合并排序算法基本原理 合…

一文看懂完整的研究生生活规划

很多人在刚从本科步入研究生生活的时候,总是对于自己三年的研究生生活没有清晰的规划,总是在各种浪费时间,没有拿到想要的东西,也没有学到想学的东西,亦或是没有找到理想的工作,最后草草的毕业。这个时候我们就应该对于自己的研究生生活有个清晰的规划,帮助我们不留遗憾…

人大与加拿大女王大学金融管理硕士项目:开启国际视野,成就金融领袖

生活中&#xff0c;我们总会遇到各种各样的困难和挑战。有时候&#xff0c;我们会感到沮丧、迷茫甚至绝望。但是&#xff0c;正是这些困难和挑战&#xff0c;让我们变得更加坚强、勇敢和成熟。在这个职场竞争愈发激烈的时代&#xff0c;不断地充实自己是非常重要的。如果你从事…

IP代理被低估的作用,你知道吗?

IP说简单不简单&#xff0c;说复杂也不复杂&#xff0c;打个比方&#xff0c;IP就好比我们上网的一个门牌号&#xff0c;每家每户都会有一个门牌号&#xff0c;而且是唯一的地址。而代理IP&#xff08;代理服务器&#xff09;是一个位于中间的服务器&#xff0c;充当客户端和目…

centos部署tomcat

Java Downloads | Oracle 上面是下载网址 Tomcat是由Apache开发的一个Servlet容器&#xff0c;实现了对Servlet和JSP的支持&#xff0c;并提供了作为Web服务器的一些特有功能&#xff0c;如Tomcat管理和控制平台&#xff0c;安全域管理和Tomcat阀 简单来说&#xff1a;Tomcat…

【人口数据集总结】WorldPop、GWPv4等

1 全球人口数据WorldPop 数据详解可参见另一博客-【数据集8】全球人口数据WorldPop详解。 WorldPop是由南安普顿大学在2013年10月发起的全球人口数据评估,将AfriPop,AsiaPop和AmeriPop人口调查项目整合到一起。数据集已经被众多的组织和机构使用:联合国开发计划署,联合国…

【多线程相关其二】进程与线程

进程vs线程 进程&#xff08;process&#xff09;指的是正在运行的程序的实例&#xff0c;即an instance of a computer that is being executed。用拆字法理解就是&#xff1a;进行中的程序。程序是一个没有生命的实体&#xff0c;只有处理器执行它的时候才能成为一个活动的实…

技术分享| anyRTC低延时直播优化

直播系统就是把活动现场的音频或视频信号经数字压缩后&#xff0c;传送到直播多媒体服务器(CDN)上&#xff0c;在互联网上供广大网友或授权特定人群收听或收看。而随着技术的日益更新&#xff0c;人民对于直播的互动性&#xff0c;实时性要求更高了&#xff0c;传统的直播少则几…

Spring Boot中配置默认的HikariCP数据源

在了解HiKari之前&#xff0c;我们需要先了解关于数据访问的相关概念&#xff1a; 什么是JDBC JDBC&#xff08;Java Database Connectivity&#xff09;是Java编程语言用于与数据库进行交互的标准API。它提供了一组类和接口&#xff0c;用于执行数据库操作&#xff0c;如连接…

JVM虚拟机:从结构到指令让你对栈有足够的认识

本文重点 在前面的课程中,我们学习了运行时数据区的大概情况,从本文开始,我们将对一些组件进行详细的介绍,本文我们将学习栈。栈内存主管java的运行,是在线程创建时创建的,它是线程私有的,它的生命周期是跟随线程的生命期,也就是说线程结束栈内存就释放了,对于栈来说…