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

网友投稿 841 2022-10-23

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

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

@[TOC]

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

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

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

注册类型转换处理器

ypeHandlerRegistry的register()方法:

private void register(Type javaType, JdbcType jdbcType, TypeHandler handler) { if (javaType != null) { Map> 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 TypeHandler getTypeHandler(Type type, JdbcType jdbcType) { if (ParamMap.class.equals(type)) { return null; } Map> 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) handler; }

调用getJdbcHandlerMap()方法根据Java类型查找对应的TypeHandler集合 如果不为空,根据jdbcType获取TypeHandler实例,如果找不到实例就使用null来获取TypeHandler的实例 如果jdbcHandlerMap只注册了一个TypeHandler,就使用这个TypeHandler对应的实例

再看一下getJdbcHandlerMap()方法:

获取jdbc类型对应的处理器

private Map> getJdbcHandlerMap(Type type) { Map> 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; }

先查找指定Java类型对应的TypeHandler集合 如果为空返回null 初始化指定Java类型的TypeHandler集合 调用getJdbcHandlerMapForSuperclass()

private Map> getJdbcHandlerMapForSuperclass(Class clazz) { Class superclass = clazz.getSuperclass(); if (superclass == null || Object.class.equals(superclass)) { return null; // 父类为Object或null则查找结束 } Map> jdbcHandlerMap = typeHandlerMap.get(superclass); if (jdbcHandlerMap != null) { return jdbcHandlerMap; } else { return getJdbcHandlerMapForSuperclass(superclass); } }

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

总结

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

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SGPlayer- 跨平台媒体播放器框架
下一篇:一款仿VLayout的可嵌套RecyclerView框架
相关文章

 发表评论

暂时没有评论,来抢沙发吧~