MyBatis 管理和查找TypeHandler的方法

 更新时间:2025年03月21日 10:53:20   作者:冰糖心书房  
MyBatis通过TypeHandlerRegistry组件集中管理和查找TypeHandler,TypeHandler用于处理Java类型和JDBC类型之间的转换,本文介绍MyBatis 管理和查找TypeHandler的方法,感兴趣的朋友一起看看吧

MyBatis 通过 TypeHandlerRegistry 组件来集中 管理和查找 TypeHandlerTypeHandler 是 MyBatis 中用于 处理 Java 类型和 JDBC 类型之间转换 的重要组件。 MyBatis 需要管理大量的 TypeHandler,并能够根据需要快速找到合适的 TypeHandler 来进行类型转换。

1. TypeHandlerRegistry 的作用:TypeHandler 的注册中心

TypeHandlerRegistry 可以被理解为 MyBatis 中 TypeHandler 的注册中心TypeHandler 的仓库。 它的核心作用是:

  • 注册 TypeHandler: 负责注册各种 TypeHandler 到 MyBatis 系统中。 TypeHandler 可以是 MyBatis 内置的,也可以是用户自定义的。
  • 存储 TypeHandler: 内部维护一个数据结构 (实际上是多个 Map) 来存储已注册的 TypeHandler,并按照不同的维度进行组织,方便查找。
  • 查找 TypeHandler: 提供 API 方法,允许 MyBatis 在运行时根据 Java 类型和/或 JDBC 类型,快速查找并获取合适的 TypeHandler 实例。

2. TypeHandlerRegistry 如何管理 TypeHandler:内部存储结构

TypeHandlerRegistry 内部使用多个 Map 来存储 TypeHandler,以便根据不同的查找条件进行高效检索。 主要的存储结构包括:

KNOWN_TYPE_HANDLERS (Map<JdbcType, TypeHandler<?>>):

  • Key: JdbcType 枚举值,代表 JDBC 类型。
  • Value: TypeHandler<?> 实例。
  • 作用: 根据 JDBC 类型查找 TypeHandler。 例如,当 MyBatis 需要处理 VARCHAR 类型的参数或结果时,会使用 KNOWN_TYPE_HANDLERS 查找与 JdbcType.VARCHAR 关联的 TypeHandler。

TYPE_HANDLER_MAP (Map<Type, Map<JdbcType, TypeHandler<?>>>):

  • Outer Key: Type 对象,代表 Java 类型。
  • Inner Key: JdbcType 枚举值,代表 JDBC 类型 (可以为 null,表示不区分 JDBC 类型)。
  • Value: TypeHandler<?> 实例。
  • 作用: 根据 Java 类型和 JDBC 类型查找 TypeHandler。 这是最主要的 TypeHandler 存储和查找结构。 MyBatis 会优先使用 TYPE_HANDLER_MAP 进行查找。
  • 层级结构: TYPE_HANDLER_MAP 是一个两层嵌套的 Map。 外层 Map 的 Key 是 Java 类型,内层 Map 的 Key 是 JDBC 类型。 这种结构允许根据 Java 类型和 JDBC 类型的组合来精确查找 TypeHandler。

ALL_TYPE_HANDLERS_MAP (Map<Class<?>, TypeHandler<?>>):

  • Key: Class<?> 对象,代表 TypeHandler 的 Class 类型。
  • Value: TypeHandler<?> 实例。
  • 作用: 根据 TypeHandler 的 Class 类型查找 TypeHandler 实例。 主要用于通过 TypeHandlerRegistry.getTypeHandler(Class<? extends TypeHandler> handlerType) 方法直接根据 TypeHandler 类型查找实例。

3. TypeHandler 的注册方式:

TypeHandler 可以通过多种方式注册到 TypeHandlerRegistry 中:

3.1. XML 配置文件 (mybatis-config.xml):

<typeHandlers> 元素和 <typeHandler> 子元素: 在 mybatis-config.xml 文件中使用 <typeHandlers> 元素和 <typeHandler> 子元素来注册 TypeHandler。

<typeHandlers>
    <typeHandler javaType="java.lang.String" jdbcType="VARCHAR" handler="com.example.typehandler.MyStringTypeHandler"/>
    <typeHandler package="com.example.typehandler.package"/> <!-- 扫描包注册 TypeHandler -->
</typeHandlers>
  • javaType 属性 (可选): 指定 TypeHandler 处理的 Java 类型。 可以指定多个 Java 类型,用逗号分隔。
  • jdbcType 属性 (可选): 指定 TypeHandler 处理的 JDBC 类型。 可以指定多个 JDBC 类型,用逗号分隔。
  • handler 属性: 指定 TypeHandler 实现类的全限定名。
  • <typeHandler package="...">: 指定包名,MyBatis 会扫描指定包下的所有 TypeHandler,并自动注册。

XMLConfigBuilder 解析 <typeHandlers> 元素时,会将配置的 TypeHandler 注册到 Configuration 对象的 typeHandlerRegistry 中。

3.2. Java 代码配置 (Configuration 对象):

Configuration.getTypeHandlerRegistry().register(...) 方法: 可以通过 Configuration 对象的 getTypeHandlerRegistry() 方法获取 TypeHandlerRegistry 实例,然后使用 register() 方法手动注册 TypeHandler。

Configuration configuration = new Configuration();
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
typeHandlerRegistry.register(String.class, JdbcType.VARCHAR, new MyStringTypeHandler()); // 注册指定 Java 类型和 JDBC 类型的 TypeHandler
typeHandlerRegistry.register(MyEnumTypeHandler.class); // 注册 TypeHandler,不指定 Java 类型和 JDBC 类型 (MyEnumTypeHandler 需要标注 @MappedTypes 和 @MappedJdbcTypes)
typeHandlerRegistry.register(new MyDefaultTypeHandler()); // 注册 TypeHandler 实例,不指定 Java 类型和 JDBC 类型 (MyDefaultTypeHandler 需要标注 @MappedTypes 和 @MappedJdbcTypes)
  • register(TypeHandler<?> typeHandler): 注册 TypeHandler 实例。TypeHandler 类需要使用 @MappedTypes@MappedJdbcTypes 注解指定它处理的 Java 类型和 JDBC 类型。
  • register(Class<?> javaType, TypeHandler<?> typeHandler): 注册指定 Java 类型的 TypeHandler 实例。
  • register(JdbcType jdbcType, TypeHandler<?> typeHandler): 注册指定 JDBC 类型的 TypeHandler 实例。
  • register(Class<?> javaType, JdbcType jdbcType, TypeHandler<?> typeHandler): 注册指定 Java 类型和 JDBC 类型的 TypeHandler 实例。
  • register(String typeHandlerName): 根据 TypeHandler 的别名注册 TypeHandler (别名需要在 <typeAliases> 中定义)。

3.3. 自动扫描包 (<typeHandlers package="...">):

  • 通过在 <typeHandlers> 元素中使用 <typeHandler package="..."> 子元素,可以指定包名。 MyBatis 会 自动扫描指定包及其子包下的所有 TypeHandler 实现类,并将它们注册到 TypeHandlerRegistry 中。
  • TypeHandler 类需要使用 @MappedTypes@MappedJdbcTypes 注解来声明它处理的 Java 类型和 JDBC 类型。

3.4. MyBatis 内置的 TypeHandler:

  • MyBatis 框架内置了大量的常用 TypeHandler,用于处理 Java 基本类型、常用 Java 类型 (例如 String, Date, Enum) 和 JDBC 类型之间的转换。
  • 这些内置的 TypeHandler 在 TypeHandlerRegistry 初始化时会被自动注册,无需显式配置。 例如: StringTypeHandler, IntegerTypeHandler, DateTypeHandler, EnumTypeHandler 等。

4. TypeHandlerRegistry 如何查找 TypeHandler:查找策略

当 MyBatis 需要进行类型转换时 (例如设置 PreparedStatement 参数,获取 ResultSet 结果),会通过 TypeHandlerRegistry 查找合适的 TypeHandler。 TypeHandlerRegistry 的查找策略如下 (优先级从高到低):

4.1. 精确匹配 Java 类型和 JDBC 类型:

MyBatis 会首先尝试 根据 Java 类型和 JDBC 类型的精确组合TYPE_HANDLER_MAP 中查找 TypeHandler。 这是最精确的查找方式,如果找到,则直接使用该 TypeHandler。

4.2. 匹配 Java 类型,忽略 JDBC 类型:

如果精确匹配 Java 类型和 JDBC 类型没有找到 TypeHandler,MyBatis 会尝试 只根据 Java 类型TYPE_HANDLER_MAP 中查找 TypeHandler (JDBC 类型设置为 null)。 这种方式适用于某些 TypeHandler 只需要根据 Java 类型进行处理,而不需要区分 JDBC 类型的情况。

4.3. 根据 JDBC 类型查找:

如果根据 Java 类型和 JDBC 类型都无法找到合适的 TypeHandler,MyBatis 会尝试 根据 JDBC 类型KNOWN_TYPE_HANDLERS 中查找 TypeHandler。 这种方式适用于某些通用的 JDBC 类型处理场景,例如处理所有 VARCHAR 类型的数据,可以使用与 JdbcType.VARCHAR 关联的 TypeHandler。

4.4. 类型继承关系查找 (Type Hierarchy):

如果以上方式都无法找到合适的 TypeHandler,MyBatis 还会 考虑 Java 类型的继承关系。 例如,如果查找 List 类型的 TypeHandler 失败,MyBatis 会尝试查找 Collection, Iterable, Object 等父类型或接口的 TypeHandler。 这种方式可以提高 TypeHandler 的通用性。

4.5. 默认 TypeHandler (Default TypeHandler):

如果经过上述所有查找策略都无法找到合适的 TypeHandler,MyBatis 会 使用默认的 ObjectTypeHandler (或其他默认 TypeHandler) 进行处理。 ObjectTypeHandler 可以处理 Object 类型的数据,但可能会丢失类型信息,性能也可能较低。

5. 关键组件和类:

  • TypeHandlerRegistry: TypeHandler 注册中心,负责管理和查找 TypeHandler。
  • TypeHandler 接口: 所有 TypeHandler 实现类都需要实现的接口,定义了类型转换的方法 (setParameter(), getResult()).
  • Configuration 对象: TypeHandlerRegistry 实例存储在 Configuration 对象中。
  • XMLConfigBuilder: 在解析 mybatis-config.xml 文件时,XMLConfigBuilder 负责解析 <typeHandlers> 元素,并将配置的 TypeHandler 注册到 Configuration 对象的 typeHandlerRegistry 中。
  • JdbcType 枚举: 定义了 JDBC 类型常量。Type 接口 (Java Reflection API): 表示 Java 类型。

总结

  • TypeHandlerRegistry 的作用和 TypeHandler 的管理和查找机制:
  • TypeHandlerRegistry 是 MyBatis 中 TypeHandler 的注册中心,负责管理和维护所有已注册的 TypeHandler。TypeHandler 可以通过 XML 配置、Java 代码配置、自动扫描包和 MyBatis 内置等多种方式注册到 TypeHandlerRegistry 中。
  • TypeHandlerRegistry 使用多层 Map 结构存储 TypeHandler,并提供高效的查找策略,可以根据 Java 类型、JDBC 类型和类型继承关系等条件查找合适的 TypeHandler。MyBatis 在运行时需要进行类型转换时,会委托 TypeHandlerRegistry 查找合适的 TypeHandler,并使用找到的 TypeHandler 进行类型转换操作。
  • TypeHandlerRegistry 的管理和查找机制保证了 MyBatis 能够灵活、高效地处理各种 Java 类型和 JDBC 类型之间的转换,实现了类型转换的解耦和可扩展性。

到此这篇关于MyBatis 管理和查找TypeHandler的方法的文章就介绍到这了,更多相关MyBatis 查找TypeHandler内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java实用工具库commons-lang3的使用

    Java实用工具库commons-lang3的使用

    Apache Commons Lang 3是一个流行的Java实用工具库,提供了对java.lang包的扩展,包括字符串操作、正则表达式处理、数字操作、日期和时间操作、随机字符串生成和对象操作等功能
    2025-03-03
  • MyBatis查询返回Map示例代码

    MyBatis查询返回Map示例代码

    这篇文章主要给大家介绍了关于MyBatis查询返回Map的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-10-10
  • SpringBoot 集成 Druid过程解析

    SpringBoot 集成 Druid过程解析

    这篇文章主要介绍了SpringBoot 集成 Druid过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • MyBatis Mapper XML中比较操作符转义问题解决

    MyBatis Mapper XML中比较操作符转义问题解决

    在使用MyBatis编写Mapper XML时,有时会遇到比较操作符需要进行转义的情况,本文主要介绍了MyBatis Mapper XML中比较操作符转义问题解决,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • Java stream流中peek用法简单示例

    Java stream流中peek用法简单示例

    这篇文章主要给大家介绍了关于Java stream流中peek用法的相关资料,Java Stream中的peek()方法也是用于查看每个元素,但不改变流的操作的方法,文中通过代码介绍的需要的朋友可以参考下
    2023-12-12
  • SpringBoot入门教程详解

    SpringBoot入门教程详解

    SpringBoot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化 Spring 应用的初始搭建以及开发过程。本文将详细为大家讲讲SpringBoot是使用,需要的可以参考一下
    2022-06-06
  • spring boot task实现动态创建定时任务的方法

    spring boot task实现动态创建定时任务的方法

    这篇文章主要介绍了spring boot task实现动态创建定时任务,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • SpringCloud-feign使用详解

    SpringCloud-feign使用详解

    Feign是Spring Cloud中的轻量级RESTful HTTP服务客户端,它通过定义接口和注解简化了服务调用,Feign支持Ribbon进行负载均衡,并且可以通过OpenFeign与Spring MVC注解结合使用,文章详细介绍了Feign的使用方法、自定义配置以及与其他组件的集成
    2025-01-01
  • 解决MybatisPlus批量插入数据报错:Error getting generated key or setting result to parameter object问题

    解决MybatisPlus批量插入数据报错:Error getting generated 

    在使用MybatisPlus进行批量插入数据时遇到空指针异常错误,分析原因是由于主键生成策略导致的,尝试通过设置useGeneratedKeys属性解决问题,但因批量插入方法限制,该方法未能成功,最终通过自定义mapper方法实现批量插入,解决了问题
    2024-09-09
  • 深入剖析Java中的各种异常处理方式

    深入剖析Java中的各种异常处理方式

    这篇文章主要介绍了深入剖析Java中的各种异常处理方式,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-07-07

最新评论