一般我们在数据库都会定义数值型的枚举常量,不管是序列化还是反序列化都是需要我们手动去转换成枚举类型的,既然这样我们能不能让它们自动转换呢?
mybatis底层给我们提供了一项功能(TypeHandle)用于我们Java的数据类型与数据库中的类型之间相互转换,其中就包含了一个枚举处理器。但是它并不能满足我们的需求,于是Mybatis-Plus对其进行了扩展:
在 mybatis 的
EnumOrdinalTypeHandler(基于枚举常量序号)
和EnumTypeHandler(基于枚举常量名)
之外提供了更加灵活的枚举处理器MybatisEnumTypeHandler(基于枚举常量属性)
只需要对枚举进行声明,即可实现枚举的自动映射
未进行声明的枚举则根据mybatis
的defaultEnumTypeHandler
的默认值EnumTypeHandler
来进行映射
一.枚举声明
声明该枚举使用 MybatisEnumTypeHandler(基于枚举常量属性)
进行映射
1.1注解标记
枚举属性使用 @EnumValue
注解,指定枚举值在数据库中存储的实际值。支持枚举类中的任意字段,如序号或编码。
@Getter
public enum Sex implements{
MAN(0, "男"),
WOMAN(1, "女");
@EnumValue // 标记数据库存的值是code
private final Integer value;
// 其他属性...
}
1.2实现接口
实现 IEnum
接口,实现 getValue
方法,指定枚举值在数据库中存储的实际值。支持枚举类中的任意字段,如序号或编码。
import java.io.Serializable;
/**
* @author hl
*/
public interface IEnum<T extends Serializable> {
/**
* 获取值
* @return 值
*/
T getValue();
}
@Getter
@AllArgsConstructor
public enum Sex implements IEnum<Integer> {
MAN(0, "男"),
WOMAN(1, "女");
private final Integer value;
private final String desc;
@Override
public Integer getValue() {
return this.value;
}
}
二.springboot如何接收枚举类型?
对于接收不同的参数,我们需给出不同的接收方式,否则会接收失败
2.1.请求行接收参数
如果我们使用的是Param参数发送:Query或Path,我们可以使用注解标记,使用 @EnumValue
注解,指定枚举值在数据库中存储的实际值
例如:其中@EnumValue
注解用于指定枚举值在数据库中存储的实际值的对应方式,@JsonValue注解用于标识给前端的返回值(标识在value之上表示返回的是Integer类型,标识在des之上表示返回的是String类型)
@Getter
public enum Sex {
MAN(0, "男"),
WOMAN(1, "女");
@EnumValue
private final Integer value;
@JsonValue
private final String desc;
Sex(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
}
2.2.请求体接收参数
如果我们接收的是 JSON 字符串类型,那么 Jackson 默认是根据下标进行转换的,和我们根据匹配值获取相应枚举不符,所以进行以下设置:
2.2.1.定义接口实现
import java.io.Serializable;
/**
* @author hl
*/
public interface IEnum<T extends Serializable> {
/**
* 获取值
* @return 值
*/
T getValue();
}
@Getter
public enum Sex implements IEnum<Integer> {
MAN(0, "男"),
WOMAN(1, "女");
@EnumValue
private final Integer value;
@JsonValue
private final String desc;
Sex(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
}
2.2.2.配置枚举类型转换器
@Component
public class EnumConvertFactory implements ConverterFactory<String, IEnum<?>> {
@Override
public <T extends IEnum<?>> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToEnum<>(targetType);
}
public static class StringToEnum<T extends IEnum<?>> implements Converter<String, T> {
private final Class<T> targetType;
public StringToEnum(Class<T> targetType) {
this.targetType = targetType;
}
@Override
public T convert(String source) {
if (!StringUtils.hasText(source)) {
return null;
}
return (T) EnumConvertFactory.getEnum(this.targetType, source);
}
}
public static <T extends IEnum<?>> T getEnum(Class<T> targetType, String source) {
for (T constant : targetType.getEnumConstants()) {
if (source.equals(String.valueOf(constant.getValue()))) {
return constant;
}
}
return null;
}
}
2.2.3.注册转换器
/**
* 配置类,注册web层相关组件
*/
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Autowired
private EnumConvertFactory enumConvertFactory;
/**
* 注册自定义枚举类型转换器
* @param registry
*/
@Override
protected void addFormatters(FormatterRegistry registry) {
log.info("注册自定义枚举类型转换器...");
registry.addConverterFactory(enumConvertFactory);
}
}
三.案例测试
例如:条件分页查询话题类型
前端:
请求方式:Get
请求URL:/user/topic/page?page=1&pageSize=5&topicStatus=1
后端:
例如:修改用户性别信息
前端:
请求方式:Put
请求URL:/user/info
后端: