Mybatis Plus自定义枚举类型转换

自定义Mybatis的枚举转换

这里实际使用的是mybatis plus的枚举工具,只不过拷贝出来修改为自己的枚举接口以及想用什么值进行转换;我这里使用的是通过数据库里面保存的数字类型进行转换,然后通过自动装配替换原生的枚举类型,原来的类型 MybatisEnumTypeHandler

java 复制代码
public class CommonEnumTypeHandler<E extends CommonEnum> extends BaseTypeHandler<E> {

    private static final Map<String, String> TABLE_METHOD_OF_ENUM_TYPES = new ConcurrentHashMap();
    private static final ReflectorFactory REFLECTOR_FACTORY = new DefaultReflectorFactory();
    private final Class<E> enumClassType;
    //当前值的字段类型
    private final Class<?> propertyType;
    //mybatis plus封装的获取值的执行器
    private final Invoker getInvoker;

    public CommonEnumTypeHandler(Class<E> enumClassType) {
        if (enumClassType == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        } else {
            //获取到前字段的枚举类型
            this.enumClassType = enumClassType;
            //获取到枚举类型
            MetaClass metaClass = MetaClass.forClass(enumClassType, REFLECTOR_FACTORY);
            String name = CommonEnum.VALUE_FILED_NAME;
            //如果枚举类型不为 CommonEnum 接口的实现类,
            if (!CommonEnum.class.isAssignableFrom(enumClassType)) {
                name = findEnumValueFieldName(this.enumClassType)
                    .orElseThrow(() -> new IllegalArgumentException(String.format("Could not find @EnumValue in Class: %s.",
                                                                                  this.enumClassType.getName())));
            }
            //通过getter方法来获取到对于属性值的类型
            this.propertyType = ReflectionKit.resolvePrimitiveIfNecessary(metaClass.getGetterType(name));
            this.getInvoker = metaClass.getGetInvoker(name);
        }
    }

    /**
     * 根据枚举类型来获取对应字段的 @EnumValue 注解的值
     *
     * @param clazz
     * @return
     */
    public static Optional<String> findEnumValueFieldName(Class<?> clazz) {
        if (clazz != null && clazz.isEnum()) {
            String className = clazz.getName();
            return Optional.ofNullable(CollectionUtils.computeIfAbsent(TABLE_METHOD_OF_ENUM_TYPES, className, (key) -> {
                Optional<Field> fieldOptional = findEnumValueAnnotationField(clazz);
                return fieldOptional.map(Field::getName).orElse(null);
            }));
        } else {
            return Optional.empty();
        }
    }

    /**
     * 处理字段上是否设置了 EnumValue
     *
     * @param clazz
     * @return
     */
    private static Optional<Field> findEnumValueAnnotationField(Class<?> clazz) {
        return Arrays.stream(clazz.getDeclaredFields()).filter((field) -> field.isAnnotationPresent(EnumValue.class)).findFirst();
    }

    /**
     * 判断是否是CommonEnum的接口实现
     *
     * @param clazz
     * @return
     */
    public static boolean isMpEnums(Class<?> clazz) {
        return clazz != null && clazz.isEnum() && (CommonEnum.class.isAssignableFrom(clazz) || findEnumValueFieldName(clazz).isPresent());
    }

    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
        if (jdbcType == null) {
            ps.setObject(i, this.getValue(parameter));
        } else {
            ps.setObject(i, this.getValue(parameter), jdbcType.TYPE_CODE);
        }

    }

    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Object value = rs.getObject(columnName, this.propertyType);
        return null == value && rs.wasNull() ? null : this.valueOf(value);
    }

    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Object value = rs.getObject(columnIndex, this.propertyType);
        return null == value && rs.wasNull() ? null : this.valueOf(value);
    }

    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Object value = cs.getObject(columnIndex, this.propertyType);
        return null == value && cs.wasNull() ? null : this.valueOf(value);
    }

    private E valueOf(Object value) {
        E[] es = (E[]) this.enumClassType.getEnumConstants();
        return (E) Arrays.stream(es).filter((e) -> this.equalsValue(value, this.getValue(e))).findAny().orElse((E) null);
    }

    protected boolean equalsValue(Object sourceValue, Object targetValue) {
        String sValue = StringUtils.toStringTrim(sourceValue);
        String tValue = StringUtils.toStringTrim(targetValue);
        return sourceValue instanceof Number
               &&
               targetValue instanceof Number
               && (new BigDecimal(sValue)).compareTo(new BigDecimal(tValue)) == 0 || Objects.equals(sValue, tValue);
    }

    private Object getValue(Object object) {
        try {
            return this.getInvoker.invoke(object, new Object[0]);
        } catch (ReflectiveOperationException var3) {
            throw ExceptionUtils.mpe(var3);
        }
    }
}

通过自动装配替换原来的枚举类型处理器

java 复制代码
/**
     * 配置mybatis plus自定义的枚举类型转换器
     *
     * @return
     */
    @Bean
    public ConfigurationCustomizer enumConfigurationCustomizer() {
        return configuration -> configuration.setDefaultEnumTypeHandler(CommonEnumTypeHandler.class);
    }
相关推荐
●VON10 分钟前
重生之我在暑假学习微服务第二天《MybatisPlus-下篇》
java·学习·微服务·架构·mybatis-plus
老华带你飞10 分钟前
口腔助手|口腔挂号预约小程序|基于微信小程序的口腔门诊预约系统的设计与实现(源码+数据库+文档)
java·数据库·微信小程序·小程序·论文·毕设·口腔小程序
hqxstudying20 分钟前
J2EE模式---服务层模式
java·数据库·后端·spring·oracle·java-ee
GM_82825 分钟前
【最新最完整】SpringAI-1.0.0开发MCP Server,搭建MCP Client 实战笔记(进阶+详细+完整代码)
java·后端·ai编程·springai·mcp
都叫我大帅哥27 分钟前
Java DelayQueue:时间管理大师的终极武器
java
秋千码途34 分钟前
小架构step系列27:Hibernate提供的validator
java·spring·架构·hibernate
都叫我大帅哥35 分钟前
TOGAF迁移规划阶段全解密:从菜鸟到达人的通关秘籍
java
探索java37 分钟前
深入理解 Spring 中的 XmlBeanFactory 原理及实践
java·spring·xmlbeanfactory
hqxstudying3 小时前
Java异常处理
java·开发语言·安全·异常
我命由我123456 小时前
Kotlin 数据容器 - List(List 概述、创建 List、List 核心特性、List 元素访问、List 遍历)
java·开发语言·jvm·windows·java-ee·kotlin·list