当前位置: 首页 > news >正文

【Mytais系列】Type模块:类型转换

MyBatis 的 类型系统(Type System) 是框架处理 Java 类型与数据库类型之间映射的核心模块,它通过 类型处理器(TypeHandler)类型别名(TypeAlias)类型转换器 等机制,实现了数据库字段与 Java 对象属性的无缝转换。以下是其核心功能、使用场景及实现原理的详解:


一、类型系统的核心组件

组件

作用

TypeHandler

处理 Java 类型与 JDBC 类型之间的转换(如 StringVARCHAR)。

TypeAlias

为 Java 类型定义别名,简化 XML 配置中的类型名称。

TypeHandlerRegistry

全局注册所有 TypeHandler,管理类型与处理器的映射关系。

ObjectFactory

创建结果集映射的 Java 对象实例(如 POJO、集合等)。


二、类型处理器(TypeHandler)

1. 功能与职责
  • 双向转换
    • 写入数据库:将 Java 对象属性转换为 JDBC 参数(PreparedStatement.setXxx)。
    • 读取数据库:将 JDBC 结果集(ResultSet.getXxx)转换为 Java 对象属性。
  • 支持复杂类型
    • 枚举、集合、自定义对象、JSON 字符串等。
2. 内置 TypeHandler

MyBatis 默认注册了常见类型的处理器,例如:

Java 类型

JDBC 类型

对应 TypeHandler

String

VARCHAR

StringTypeHandler

Integer

INTEGER

IntegerTypeHandler

Date

TIMESTAMP

DateTypeHandler

boolean

BOOLEAN

BooleanTypeHandler

枚举类

VARCHAR

EnumTypeHandler(按名称存储)

枚举类(按序数存储)

INTEGER

EnumOrdinalTypeHandler

3. 自定义 TypeHandler

当默认处理器无法满足需求时(如处理 JSON 字段),可自定义 TypeHandler

示例:将 Java 对象序列化为 JSON 字符串存入数据库

// 1. 实现 TypeHandler 接口
@MappedTypes(User.class)    // 指定处理的 Java 类型
@MappedJdbcTypes(JdbcType.VARCHAR)  // 指定对应的 JDBC 类型
public class JsonTypeHandler implements TypeHandler<User> {private final ObjectMapper objectMapper = new ObjectMapper();// 写入数据库时,将 User 对象转为 JSON 字符串@Overridepublic void setParameter(PreparedStatement ps, int i, User parameter, JdbcType jdbcType) throws SQLException {try {String json = objectMapper.writeValueAsString(parameter);ps.setString(i, json);} catch (JsonProcessingException e) {throw new SQLException("JSON 序列化失败", e);}}// 从数据库读取时,将 JSON 字符串转为 User 对象@Overridepublic User getResult(ResultSet rs, String columnName) throws SQLException {String json = rs.getString(columnName);return parseJson(json);}// 其他重载方法(如 getResult(ResultSet rs, int columnIndex))// ...private User parseJson(String json) {try {return objectMapper.readValue(json, User.class);} catch (JsonProcessingException e) {throw new RuntimeException("JSON 解析失败", e);}}
}

注册自定义 TypeHandler

<!-- mybatis-config.xml -->
<typeHandlers><typeHandler handler="com.example.JsonTypeHandler"/>
</typeHandlers>

在 Mapper 中使用

<resultMap id="userResultMap" type="User"><result column="json_data" property="data" typeHandler="com.example.JsonTypeHandler"/>
</resultMap>

三、类型别名(TypeAlias)

1. 功能
  • 简化配置:为长类名定义短别名,避免 XML 中重复书写全限定类名。
  • 提升可读性:例如将 java.util.List 别名为 list
2. 使用方式

方式一:XML 配置

<!-- mybatis-config.xml -->
<typeAliases><typeAlias type="com.example.User" alias="User"/><package name="com.example.dto"/> <!-- 自动扫描包下所有类,别名为首字母小写的类名 -->
</typeAliases>

方式二:注解配置

@Alias("User")  // 在类上添加注解
public class User { ... }

在 Mapper 中使用别名

<select id="getUser" resultType="User">  <!-- 直接使用别名 -->SELECT * FROM users WHERE id = #{id}
</select>

四、类型处理器注册表(TypeHandlerRegistry)

1. 职责
  • 全局管理 TypeHandler:维护 Java类型 ↔ JDBC类型 ↔ TypeHandler 的映射关系。
  • 自动发现机制:通过 <typeHandlers> 配置或扫描包路径注册处理器。
2. 优先级规则

当多个 TypeHandler 可处理同一类型时,按以下顺序选择:

  1. 显式指定 typeHandler 属性的处理器。
  2. 注解 @MappedTypes@MappedJdbcTypes 精确匹配的处理器。
  3. 默认注册的处理器(如 StringTypeHandler)。

五、常见应用场景

1. 处理枚举类型
  • 按名称存储(默认):使用 EnumTypeHandler,将枚举的 name() 存入数据库。
  • 按序数存储:使用 EnumOrdinalTypeHandler,将枚举的 ordinal() 存入数据库。
  • 自定义存储逻辑:实现 TypeHandler 接口,例如将枚举转换为特定代码值。
2. 处理复杂类型
  • JSON 字段:如上述 JsonTypeHandler 示例。
  • 加密字段:自定义处理器,在写入时加密、读取时解密敏感数据(如手机号、身份证号)。
3. 处理集合类型
  • 默认支持:MyBatis 内置 ListTypeHandlerMapTypeHandler,但通常直接通过 resultMap 映射集合属性,无需手动处理。

六、最佳实践

1. 合理使用类型别名
  • 统一管理:在 mybatis-config.xml 中集中定义别名,避免分散配置。
  • 避免冲突:确保不同包下的类别名唯一,或直接使用全限定类名。
2. 自定义 TypeHandler 的注意事项
  • 线程安全:确保 TypeHandler 无状态或使用线程安全的数据结构(如上述 ObjectMapper 可复用)。
  • 异常处理:捕获并转换异常为 SQLException,避免框架层面崩溃。
3. 性能优化
  • 缓存复杂对象:若频繁解析 JSON 或加密数据,可添加缓存层(如 ConcurrentHashMap)。
  • 避免过度自定义:优先使用 MyBatis 内置处理器,减少不必要的复杂性。

七、总结

MyBatis 的类型系统通过 类型处理器类型别名 等机制,屏蔽了 Java 对象与数据库类型之间的差异,使开发者能够专注于业务逻辑。通过合理使用内置功能并扩展自定义 TypeHandler,可以高效处理复杂数据类型,提升代码可维护性和灵活性。

相关文章:

  • VBA 64位API声明语句第009讲
  • RUST变量学习笔记
  • 【AI面试准备】XMind拆解业务场景识别AI赋能点
  • 2025年渗透测试面试题总结-拷打题库36(题目+回答)
  • 迭代器的思想和实现细节
  • 【计算机视觉】三维重建: OpenMVS:工业级多视图立体视觉重建框架
  • 腾讯混元-DiT 文生图
  • 基于Jenkins的DevOps工程实践之Jenkins共享库
  • Python 数据智能实战 (10):智能商品推荐 - LLM “猜你喜欢”
  • ES6语法
  • 驱动精灵v9.7(含网卡版)驱动工具软件下载及安装教程
  • MySQL 日期加减函数详解
  • 进程间通信(IPC)
  • sql 注入中的万能密码
  • iOS启动优化:从原理到实践
  • ActiveMQ 集群搭建与高可用方案设计(二)
  • 大数据:数字时代的驱动力
  • 数据库原理与应用实验二 题目七
  • Oracle 11g通过dg4odbc配置dblink连接神通数据库
  • 前端面试每日三题 - Day 23
  • 江苏淮安优化村级资源配置:淮安区多个空心村拟并入邻村
  • 央行行长详解降准:将释放长期流动性1万亿,整体存款准备金率平均水平降至6.2%
  • 韩正出席庆祝中国欧盟建交50周年招待会并致辞
  • “子宫内膜异位症”相关论文男性患者样本超六成?福建省人民医院展开调查
  • 甘肃省政府原党组成员、副省长杨子兴被提起公诉
  • 探访小剧场、直播间、夜经济:五一假期多地主官调研新消费