聊聊Mybatis的类型转换注册类TypeHandlerRegistry

举报
周杰伦本人 发表于 2022/08/29 22:09:19 2022/08/29
【摘要】 聊聊Mybatis的类型转换注册类TypeHandlerRegistry 注册类型转换处理器 获取类型处理器 获取jdbc类型对应的处理器 总结 聊聊Mybatis的类型转换注册类TypeHandlerRegistry上篇文章中我们说到TypeHandler是进行类型转换的接口,它有针对不同的类型有很多实现类,TypeHandlerRegistry来进行统一管理Mybatis初始化Type...

聊聊Mybatis的类型转换注册类TypeHandlerRegistry

上篇文章中我们说到TypeHandler是进行类型转换的接口,它有针对不同的类型有很多实现类,TypeHandlerRegistry来进行统一管理

Mybatis初始化TypeHandler后,调用TypeHandlerRegistry的register()方法进行注册,下面就看一下register()

注册类型转换处理器

ypeHandlerRegistry的register()方法:

private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) {
        if (javaType != null) { 
            Map<JdbcType, TypeHandler<?>> map = typeHandlerMap.get(javaType);
            if (map == null || map == NULL_TYPE_HANDLER_MAP) {
                map = new HashMap<>();
            }
            map.put(jdbcType, handler);
            typeHandlerMap.put(javaType, map);
        }
        allTypeHandlersMap.put(handler.getClass(), handler);
    }

allTypeHandlersMap中保存着所有TypeHandler类型和它对应的实例,除了这个register()方法,还可以根据@MappedJdbcTypes和@MappedTypes注解获取数据,@MappedTypes配置配置TypeHandler接口与Java类型的集合,@MappedJdbcTypes配置TypeHandler接口与Jdbc类型的集合,TypeHandlerRegistry的构造方法中调用了很多注册方法对不同jdbc类型选择不同TypeHandler的实例来进行注册

完成类型与TypeHandler实例的注册后,mybatis会根据java类型和jdbc类型来查找对应的TypeHandler实例,调用方法是TypeHandlerRegistry的getTypeHandler()方法:

获取类型处理器

TypeHandlerRegistry的getTypeHandler()方法:

private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
        if (ParamMap.class.equals(type)) {
            return null;
        }
        Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = getJdbcHandlerMap(type);
        TypeHandler<?> handler = null;
        if (jdbcHandlerMap != null) {
            handler = jdbcHandlerMap.get(jdbcType);
            if (handler == null) {
                handler = jdbcHandlerMap.get(null);
            }
            if (handler == null) {
                handler = pickSoleHandler(jdbcHandlerMap);
            }
        }
        // type drives generics here
        return (TypeHandler<T>) handler;
    }
  1. 调用getJdbcHandlerMap()方法根据Java类型查找对应的TypeHandler集合
  2. 如果不为空,根据jdbcType获取TypeHandler实例,如果找不到实例就使用null来获取TypeHandler的实例
  3. 如果jdbcHandlerMap只注册了一个TypeHandler,就使用这个TypeHandler对应的实例

再看一下getJdbcHandlerMap()方法:

获取jdbc类型对应的处理器

private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMap(Type type) {
        Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(type);
        if (NULL_TYPE_HANDLER_MAP.equals(jdbcHandlerMap)) { // 检测是否为空集合标识
            return null;
        }
        if (jdbcHandlerMap == null && type instanceof Class) {
            Class<?> clazz = (Class<?>) type;
            if (Enum.class.isAssignableFrom(clazz)) { // 针对枚举类型的处理
                Class<?> enumClass = clazz.isAnonymousClass() ? clazz.getSuperclass() : clazz;
                jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(enumClass, enumClass);
                if (jdbcHandlerMap == null) {
                    register(enumClass, getInstance(enumClass, defaultEnumTypeHandler));
                    return typeHandlerMap.get(enumClass);
                }
            } else {
                // 查找父类关联的TypeHandler集合,并将其作为clazz对应的TypeHandler集合
                jdbcHandlerMap = getJdbcHandlerMapForSuperclass(clazz);
            }
        }
        // 如果上述查找皆失败,则以NULL_TYPE_HANDLER_MAP作为clazz对应的TypeHandler集合
        typeHandlerMap.put(type, jdbcHandlerMap == null ?
                NULL_TYPE_HANDLER_MAP : jdbcHandlerMap);
        return jdbcHandlerMap;
    }
  1. 先查找指定Java类型对应的TypeHandler集合
  2. 如果为空返回null
  3. 初始化指定Java类型的TypeHandler集合
  4. 调用getJdbcHandlerMapForSuperclass()
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMapForSuperclass(Class<?> clazz) {
        Class<?> superclass = clazz.getSuperclass();
        if (superclass == null || Object.class.equals(superclass)) {
            return null; // 父类为Object或null则查找结束
        }
        Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(superclass);
        if (jdbcHandlerMap != null) {
            return jdbcHandlerMap;
        } else {
            return getJdbcHandlerMapForSuperclass(superclass);
        }
    }

这个方法是返回给定class的父类对应的jdbcHandlerMap集合,这里用到了递归。

总结

这篇文章主要讲解了类型转换注册类的TypeHandlerRegistry的注册方法和根据Java类型获取对应的TypeHandler实例的功能,注册类是重要的一个类,Mybatis的类型转换都需要在这个类进行注册才能实现类型转换

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。