springboot mybatis、mybatisplus 枚举类型转换,日期格式转换
枚举类型转换
枚举基础
1、枚举不可继承类可以实现接口
2、一般我们使用枚举 有两个属性 label(有的地方也写成name)、value ,以下是样例
public enum GenderEnum implements BaseEnum {
MALE("男", 0),
FEMALE("女", 1),
UNKNOWN("未知", 2);
private String label;
@EnumValue
private Integer value;
GenderEnum(String label, Integer value) {
this.label = label;
this.value = value;
}
GenderEnum() {
}
@Override
public Integer getValue() {
return value;
}
@Override
public String getLabel() {
return label;
}
}
3、由于我们一个项目里会定义很多枚举,每个枚举大多都有label、value两个属性,因此我们写一个枚举基类BaseEnum,所有枚举都实现它,方便转换
public interface BaseEnum {
/**
* 获取枚举值
*
* @return
*/
Integer getValue();
/**
* 获取枚举文本
*
* @return
*/
String getLabel();
/**根据枚举值和type获取枚举*/
public static <T extends BaseEnum> T getEnum(Class<T> type, int value) {
T[] objs = type.getEnumConstants();
for (T em : objs) {
if (em.getValue().equals(value)) {
return em;
}
}
return null;
}
}
springboot枚举入参,requestBody返回枚举转换
枚举入参springboot有做枚举入参默认转换实现但有限制(具体需要自己查),为了灵活需要自己定义枚举转换器,springboot默认使用jackson做json转换器,因此这里我们自己定义序列化和反序列化json转换器
1、BaseEnumDeserializer 枚举序列化类
public class BaseEnumSerializer extends JsonSerializer<BaseEnum> {
@Override
public void serialize(BaseEnum value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeNumber(value.getValue());
gen.writeStringField(gen.getOutputContext().getCurrentName() + "Text", value.getLabel());
}
}
2、BaseEnumDeserializer 枚举反序列化类
public class BaseEnumDeserializer extends JsonDeserializer<BaseEnum> {
@Override
public BaseEnum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode node = p.getCodec().readTree(p);
String currentName = p.currentName();
Object currentValue = p.getCurrentValue();
Class findPropertyType = null;
findPropertyType = BeanUtils.findPropertyType(currentName, currentValue.getClass());
if (findPropertyType == null) {
throw new IllegalArgumentException("在" + currentValue.getClass() + "实体类中找不到" + currentName + "字段");
}
String asText = null;
asText = node.asText();
BaseEnum valueOf = null;
if (!StringUtils.isEmpty(asText)) {
valueOf = BaseEnum.getEnum(findPropertyType, Integer.parseInt(asText));
}
return valueOf;
}
}
3、枚举入参
public class BaseEnumConverterFactory implements ConverterFactory<String, BaseEnum> {
@Override
public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
return new BaseEnumConverter(targetType);
}
public class BaseEnumConverter<String, T extends BaseEnum> implements Converter<String, BaseEnum> {
private Class<T> type;
public BaseEnumConverter(Class<T> type) {
this.type = type;
}
@Override
public BaseEnum convert(String source) {
return BaseEnum.getEnum(type, Integer.parseInt((java.lang.String) source));
}
}
}
mybatis写库读库枚举转换
配置文件增加转换类包扫描
mybatisPlus:
typeEnumsPackage: com.ctillnow.user.enums
typeHandlersPackage: com.ctillnow.handler.EnumTypeHandler
这里需要写一个枚举转换器继承 org.apache.ibatis.type.BaseTypeHandler
/**mybatis 把value转换成具体枚举的处理器*/
@MappedTypes(value = BaseEnum.class)
public class EnumTypeHandler<T extends BaseEnum> extends BaseTypeHandler<BaseEnum> {
private Class<T> type;
public EnumTypeHandler(Class<T> type) {
this.type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, BaseEnum parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.getValue());
}
@Override
public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
return convert(rs.getInt(columnName));
}
@Override
public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return convert(rs.getInt(columnIndex));
}
@Override
public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return convert(cs.getInt(columnIndex));
}
private T convert(int value) {
return BaseEnum.getEnum(type, value);
}
}
mybatisplus 枚举类型转换
方式一: 使用 @EnumValue 注解枚举属性 完整示例(opens new window)
public enum GradeEnum {
PRIMARY(1, "小学"), SECONDORY(2, "中学"), HIGH(3, "高中");
GradeEnum(int code, String descp) {
this.code = code;
this.descp = descp;
}
@EnumValue//标记数据库存的值是code
private final int code;
//。。。
}
方式二: 枚举属性,实现 IEnum 接口如下:
public enum AgeEnum implements IEnum<Integer> {
ONE(1, "一岁"),
TWO(2, "二岁"),
THREE(3, "三岁");
private int value;
private String desc;
@Override
public Integer getValue() {
return this.value;
}
}
将写好的json转换器,枚举类型转换器加入springboot配置
前置条件是所有的配置类都能被springboot扫描到如下
@ComponentScan(basePackages = {"com.ctillnow"})
注入json转换配置类
@Configuration
public class BeanConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
BaseEnumSerializer baseEnumSerializer = new BaseEnumSerializer();
BaseEnumDeserializer baseEnumDeserializer = new BaseEnumDeserializer();
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault()).
serializerByType(BaseEnum.class, baseEnumSerializer).
deserializerByType(Enum.class, baseEnumDeserializer);
}
}
注入枚举转换配置类
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new BaseEnumConverterFactory());
}
}
日期类型转换
在日期类型属性上使用@JsonFormat注解
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
一些问题
1、一些实体类建在公共项目中,建实体类时需使用mybatisplus的注解,但这个项目被其他项目引入不需要配置数据源
解决:引入mybatis-plus-annotation不需要配置数据源也能使用相关注解,类
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>3.2.0</version>
</dependency>