枚举讲解
我个人理解是我们建立枚举的时候,其实是很类似数据字典的东西,如果我们不建表去记录的话,这个时候就可以用枚举去表示了。
相信后端的同学都经历过一个情况,比如性别这个字段,分别值和名称对应1男、2女,这个字段在数据库时是数值类型,而前端展示则是展示字符串的名称。有几种常见实现方案呢?
-
数据库查询 sql 通过 case 判断,返回名称,以前 oracle 经常这么做
-
数据库返回的值,重新遍历赋值进去,这时候还需要判断这个值到底是男是女。
-
前端写死,返回 1 就是男,返回 2 就是女。
相信无论哪种方法都有其缺点,所以我们可以使用 mybatis-plus 提供的方式。我们在返回给前端时:
-
后端直接返回 这个枚举,让前端去get这个枚举的 name,不需要再次判断。
-
也可以后端在定义枚举类的地方,直接指定返回的字段
引入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.46</version>
</dependency>
定义枚举
我这里先把所有代码列出来,再慢慢讲解
- 性别枚举类,需要实现 IEnum 接口,不然下面扫描不到
mport com.baomidou.mybatisplus.core.enums.IEnum;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum SexEnum implements IEnum<Integer> {
women(0,"女"),
man(1,"男");
private int code;
private String name;
// 构造方法
SexEnum(int code, String name) {
this.code = code;
this.name = name;
}
//标记数据库存的值是code
@Override
public Integer getValue() {
return code;
}
public String getName() {
return name;
}
public int getCode() {
return code;
}
//前端传值保存时判断使用
public static SexEnum getByCode(int code){
for(SexEnum sexEnum:SexEnum.values()){
if(sexEnum.getCode()==code){
return sexEnum;
}
}
return null;
}
//前端返回值
@Override
public String toString() {
return name;
}
//作为数据字典返回
public static final List<Map<String,Object>> list = new ArrayList<>();
static{
for(SexEnum temp : SexEnum.values()){
Map<String,Object> map = new HashMap<>();
map.put("code",temp.code);
map.put("name", temp.name);
list.add(map);
}
}
}
- 实体类
@Data
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "s", type = IdType.ASSIGN_UUID)
private String s;
private String sname;
private Integer sage;
//数据库是int类型,保存的是枚举的code
private SexEnum ssex;
}
保存到数据库
- 我在定义枚举类的时候指定了实际保存到数据库的字段ssex,就是枚举类中code,0或1
//标记数据库存的值是code
@Override
public Integer getValue() {
return code;
}
- 前端传值的时候就传0或1,在枚举类已经有定义通过code获得枚举的方法SexEnum.getByCode(String code)
@GetMapping(value = "/test5")
public Result test5(Integer ssex) {
Student student = new Student();
student.setSage(12);
student.setSname("test2");
student.setSsex(SexEnum.getByCode(ssex));
studentMapper.insert(student);
return Result.success("ccccc");
}
序列化枚举值为数据库值(返回前端)
上面说了这里也是有两种情况
-
直接返回枚举类的,就直接在枚举类上面加注解@JsonFormat(shape = JsonFormat.Shape.OBJECT),这种我个人不太推荐
-
返回枚举类的name字段内容,男或女作为性别ssex返回
-
配置文件扫描枚举
mybatis-plus: # 支持统配符 * 或者 ; 分割,指定枚举文件 typeEnumsPackage: com.example.untitl3.enums
-
序列化枚举值的返回,SerializerFeature.WriteEnumUsingToString);
@Configuration public class WebConfiguration implements WebMvcConfigurer { /** * 使用阿里 fastjson 作为 JSON MessageConverter 实体返回null的时候可以变成空字符串等等 * @param converters */ @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { //移除原来的转换器 Iterator<HttpMessageConverter<?>> iterator = converters.iterator(); while(iterator.hasNext()){ HttpMessageConverter<?> converter = iterator.next(); if(converter instanceof MappingJackson2HttpMessageConverter){ iterator.remove(); } } FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures( // 保留 Map 空的字段 SerializerFeature.WriteMapNullValue, // 将 String 类型的 null 转成"" SerializerFeature.WriteNullStringAsEmpty, // 将 Number 类型的 null 转成 0 // SerializerFeature.WriteNullNumberAsZero, // 将 List 类型的 null 转成 [] SerializerFeature.WriteNullListAsEmpty, // 将 Boolean 类型的 null 转成 false // SerializerFeature.WriteNullBooleanAsFalse, // 避免循环引用 SerializerFeature.DisableCircularReferenceDetect, //枚举类返回前端使用toString()方法的值 SerializerFeature.WriteEnumUsingToString); converter.setFastJsonConfig(config); converter.setDefaultCharset(Charset.forName("UTF-8")); List<MediaType> mediaTypeList = new ArrayList<>(); // 解决中文乱码问题,相当于在 Controller 上的 @RequestMapping 中加了个属性 produces = "application/json" mediaTypeList.add(MediaType.APPLICATION_JSON); converter.setSupportedMediaTypes(mediaTypeList); converters.add(converter); }
-
重写枚举类的toString方法,上面代码已经列出
-
返回数据字典
有时候我们的搜索条件需要整个枚举的所有信息,然后我这里在枚举类也定义了静态变量list来记录
//作为数据字典返回
public static final List<Map<String,Object>> list = new ArrayList<>();
static{
for(SexEnum temp : SexEnum.values()){
Map<String,Object> map = new HashMap<>();
map.put("code",temp.code);
map.put("name", temp.name);
list.add(map);
}
}