com.liu.susu.enums.SexEnum cannot be cast to com.liu.susu.enums.config.IEnum
package com.liu.susu.enums.config;
/**
* @description
* @Author susu
**/
public interface IEnum<E extends Enum<?>, T> {
Object getValue();
String getName();
}
package com.liu.susu.enums.config.handler;
import cn.hutool.core.util.ClassUtil;
import com.liu.susu.enums.SexEnum;
import com.liu.susu.enums.config.IEnum;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.Set;
/**
* @FileName MybatisEnumHandler
* @Description 枚举类型处理器
* 自动将实体类中类型为 MyEnum 子类的属性,转换为枚举
* @Author susu
**/
//此注解告诉 mybatis 遇到此 SexEnum.class类型时,使用此处理器处理
@MappedTypes(value = {SexEnum.class})
public class MybatisEnumHandler<E extends Enum<E> & IEnum> extends BaseTypeHandler<E> {
public static String enumPackage;
/**
* 动态修改@MappedTypes(value = {})的value值
* 原理:类的注解,是动态代理生成的类,通过获取代理对象,反射修改其值
*/
static {
try {
MappedTypes annotation = MybatisEnumHandler.class.getAnnotation(MappedTypes.class);
InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
memberValues.setAccessible(true);
// Map values = (Map) memberValues.get(invocationHandler);
// Set> classes = ClassUtil.scanPackageBySuper(enumPackage, IEnum.class);
// Class[] allMyEnums = classes.toArray(new Class[classes.size()]);
// values.put("value", allMyEnums);
/**
* classes.size() > 0 判断一下,不然如果没有一个枚举继承 IEnum,启动报错
*/
Set<Class<?>> classes = ClassUtil.scanPackageBySuper(enumPackage, IEnum.class);
Map values = (Map) memberValues.get(invocationHandler);
if (classes.size() > 0) {
Class[] allMyEnums = classes.toArray(new Class[classes.size()]);
values.put("value", allMyEnums);
}
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
private final Class<E> type;
/**
* construct with parameter.
*/
public MybatisEnumHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType)
throws SQLException {
// ps.setString(i, parameter.getValue());
ps.setObject(i, parameter.getValue());
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
String code = rs.getString(columnName);
return rs.wasNull() ? null : this.codeOf(this.type, code);
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String code = rs.getString(columnIndex);
return rs.wasNull() ? null : this.codeOf(this.type, code);
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String code = cs.getString(columnIndex);
return cs.wasNull() ? null : this.codeOf(this.type, code);
}
public <T extends Enum<?> & IEnum> T codeOf(Class<T> enumClass, String code) {
T[] enumConstants = enumClass.getEnumConstants();
for (T t : enumConstants) {
if (t.getValue().equals(code)) {
return t;
}
}
return null;
}
}
package com.liu.susu.enums.config;
import com.liu.susu.enums.config.handler.MybatisEnumHandler;
import org.apache.ibatis.type.TypeHandler;
import org.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
/**
* @FileName MainConfig
* @Description MybatisProperties后置处理器,配置MyBatis的枚举处理器typeHandle
* 相当用户在yml中配置: mybatis.type-handlers-package
* @Author susu
**/
@Configuration
@ConditionalOnClass({TypeHandler.class, MybatisProperties.class})
public class MainConfig implements BeanPostProcessor {
@Value("${susu.mybatis.enumPackage:null}")
String enumPackage;
public static final String HANDLER_PACKAGE = "com.liu.susu.enums.config.handler";
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof MybatisProperties) {
if (!StringUtils.hasText(enumPackage)) {
enumPackage = getMainClassPackage();
}
MybatisEnumHandler.enumPackage = enumPackage;
MybatisProperties properties = (MybatisProperties) bean;
String src = properties.getTypeHandlersPackage();
if (src != null) {
// mybatis.type-handlers-package可以接受多个路径,分隔符有多种,英文逗号为其中一种
src += "," + HANDLER_PACKAGE;
} else {
src = HANDLER_PACKAGE;
}
properties.setTypeHandlersPackage(src);
}
return bean;
}
/**
* 获取main方法启动类所在的包
* @return
*/
public static String getMainClassPackage() {
StackTraceElement[] stackTraceElements = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTraceElements) {
if ("main".equals(stackTraceElement.getMethodName())) {
String mainClassName = stackTraceElement.getClassName();
return mainClassName.substring(0, mainClassName.lastIndexOf("."));
}
}
return "";
}
}
toString()
方法 + SerializerFeature.WriteEnumUsingToString
,如下:toString()
方法改一下即可Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `com.liu.susu.enums.SexEnum` from String "02": not one of the values accepted for Enum class: [GIRL, BOY]; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `com.liu.susu.enums.SexEnum` from String "02": not one of the values accepted for Enum class: [GIRL, BOY]
at [Source: (PushbackInputStream); line: 1, column: 24] (through reference chain: com.liu.susu.pojo.entity.DogEntity["dogSex"])]
package com.liu.susu.enums.utils;
import com.liu.susu.enums.config.IEnum;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Method;
/**
* description
* @author susu
**/
@Slf4j
public class EnumUtils {
public static <T extends Enum<T>> T valueOf(Class<T> enumType, Object value) {
try {
Method method = enumType.getMethod("values");
Enum[] enums = (Enum[])method.invoke(enumType);
for(int i = 0; i < enums.length; i++) {
T e = (T) enums[i];
if (((IEnum)e).getValue().equals(value)) {
return e;
}
}
return null;
} catch (Exception e) {
log.error("method values is not found in " + enumType.getClass().getName(), e);
return null;
}
}
}
② MyEnumDeserializer.java
package com.liu.susu.enums.external;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.liu.susu.enums.SexEnum;
import com.liu.susu.enums.utils.EnumUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
/**
* description 解析枚举用
* @author susu
**/
@Slf4j
public class MyEnumDeserializer extends JsonDeserializer<Enum<? extends Enum<?>>> {
public MyEnumDeserializer() {
}
public Enum<? extends Enum<?>> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
try {
String enumValue = jsonParser.getText();
if (StringUtils.isNotEmpty(enumValue)){
return getMyEnum(jsonParser.getCurrentName(), jsonParser.getText());
}else {
return null;
}
} catch (Exception var5) {
throw new RuntimeException("枚举解析错误,字段属性为:" + jsonParser.getCurrentName()
+ ", 传的枚举value为:" + jsonParser.getText());
}
}
/**
* description :根据实体属性 和 接收到的值,返回对应的枚举
*/
public Enum<? extends Enum<?>> getMyEnum(String propertyKey, String enumKey) {
return EnumUtils.valueOf(SexEnum.class, enumKey);
}
}
③ 实体加注解:@JsonDeserialize(using = MyEnumDeserializer.class)
package com.liu.susu.enums;
import com.liu.susu.enums.config.IEnum;
/**
* @Description:
* @Author susu
*/
public enum SexEnum implements IEnum {
GIRL("01","女孩"),
BOY("02","男孩");
private String value;
private String name;
SexEnum(String value, String name) {
this.value = value;
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
package com.liu.susu.controller.pet;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.liu.susu.service.pet.DogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* description 狗狗增删改查,领养等业务处理
* @author susu
**/
@Controller
@RequestMapping("/pet/dog")
@Slf4j
public class DogController {
@Autowired
private DogService dogService;
@ResponseBody
@GetMapping("/selectAllDogs")
public String selectAllDogs(){
return JSONObject.toJSONString(dogService.selectAllDogs(),
SerializerFeature.WriteEnumUsingToString);
}
}
直接看图:
'${@[email protected]()}'
<insert id="insertDog" parameterType="com.liu.susu.pojo.entity.DogEntity">
insert into dog (dog_name,dog_age,dog_sex)
values
(
#{dogName,jdbcType=VARCHAR},
#{dogAge,jdbcType=INTEGER},
#{dogSex,jdbcType=VARCHAR,
javaType=com.liu.susu.enums.SexEnum,
typeHandler=com.liu.susu.enums.config.handler.MybatisEnumHandler}
)
insert>