美文网首页
Mybatis 枚举转换器

Mybatis 枚举转换器

作者: htger | 来源:发表于2021-06-01 15:06 被阅读0次

枚举在数据库中,通常以数值存储。为了方便枚举的使用,抽象超类SerializableEnum 实现序列化和反序列化。

定义超类

public interface SerializableEnum {

    Map<Map.Entry<?, ?>, SerializableEnum> CACHE = new HashMap<>();

    int getCode();

    /**
    * 静态构造函数
    */
    static <T extends Enum<?> & SerializableEnum> T from(Class<T> cls, Integer code) {
        if (code == null || cls == null) {
            return null;
        }

        ImmutablePair<Class<T>, Integer> key = ImmutablePair.of(cls, code);
        if (CACHE.containsKey(key)) {
            return (T) CACHE.get(key);
        }

        // 没有缓存
        BeanInfo beanInfo = null;
        try {
            beanInfo = Introspector.getBeanInfo(cls, Object.class);
        } catch (IntrospectionException e) {
            e.printStackTrace();
            return null;
        }
        MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();

        if (methodDescriptors != null && methodDescriptors.length > 0) {
            Optional<MethodDescriptor> valuesMethod = Arrays.stream(methodDescriptors)
                    .filter(m -> Objects.equals(m.getName(), "values"))
                    .findAny();

            if (valuesMethod.isPresent()) {
                T[] invoke = null;
                try {
                    invoke = (T[]) valuesMethod.get().getMethod().invoke(cls);
                } catch (IllegalAccessException | InvocationTargetException e) {
                    return null;
                }

                return Arrays.stream(invoke)
                        .filter(it -> Objects.deepEquals(it.getCode(), code))
                        .peek(it -> CACHE.put(
                                key, it
                        ))
                        .findAny()
                        .orElse(null);

            }
        }
        return null;
    }
}

具体枚举

public enum GroupRole implements SerializableEnum {
    /**
     * 群主
     */
    OWNER(1),
    /**
     * 管理员
     */
    MANAGER(2),
    /**
     * 普通成员
     */
    MEMBER(3);

    @Getter
    private final int code;

    GroupRole(int code) {
        this.code = code;
    }
}

mybatis typehandler

通用转换器

public abstract class SerializableEnumTypeHandler<T extends Enum<?> & SerializableEnum> extends BaseTypeHandler<T> {

    private Class<T> argTypeOfImplClass;

    public SerializableEnumTypeHandler() {
        ResolvableType resolvableType = ResolvableType.forType(this.getClass().getGenericSuperclass());
        Class<?>[] classes = resolvableType.resolveGenerics();
        argTypeOfImplClass = (Class<T>) classes[0];
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        ps.setInt(i, parameter.getCode());
    }

    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return SerializableEnum.from(argTypeOfImplClass, rs.getInt(columnName));
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return SerializableEnum.from(argTypeOfImplClass, rs.getInt(columnIndex));
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return null;
    }
}

具体 typehandler

@MappedJdbcTypes(JdbcType.INTEGER)
public class GroupMemberRoleTypeHandler extends SerializableEnumTypeHandler<GroupMemberRole> {

}

我想问

  • 如何注册实现了接口的枚举的 typehandler
    在typehandler上添加@MappedTypes 添加实现的接口。 参考

  • 如何使用IDE的文件模板快速创建枚举类 参考

相关文章

网友评论

      本文标题:Mybatis 枚举转换器

      本文链接:https://www.haomeiwen.com/subject/zziwsltx.html