MyBatis TypeHandler 详解与实战:FastJson 实现字符串转 List

在 MyBatis 中,TypeHandler 是实现 Java 类型与数据库类型双向转换 的核心组件。无论是处理基础数据类型还是复杂的 JSON、枚举或自定义对象,它都能通过灵活的扩展机制满足开发需求。本文将通过一个 将数据库 JSON 字符串转换为 List<User> 的案例,详解 TypeHandler 的原理与实践。


一、TypeHandler 的作用与原理

1. 核心功能

  • 类型转换桥梁 :将 Java 对象属性转换为 JDBC 参数(如 PreparedStatement 设置值);
  • 结果集映射 :将数据库查询结果(如 ResultSet)转换为 Java 对象属性;
  • 空值处理 :统一处理 Java 对象与数据库字段的 NULL 值逻辑。

2. 应用场景

  • 内置类型处理 :MyBatis 已支持 StringIntegerDate 等常见类型的转换;
  • 复杂类型处理:如 JSON 字符串与对象互转、枚举值与数据库标记映射、CSV 字符串与集合转换等。

二、TypeHandler 的配置与扩展

1. 内置 TypeHandler

MyBatis 默认提供多种 TypeHandler,例如:

  • StringTypeHandler:处理 VARCHARString
  • EnumTypeHandler:处理枚举与数据库标记(如 disabled0);
  • DateTypeHandler:处理日期类型与 TIMESTAMP 的转换。

2. 自定义 TypeHandler 步骤

  1. 继承 BaseTypeHandler :实现 setNonNullParameter(Java→JDBC)和 getNullableResult(JDBC→Java)方法;
  2. 注册处理器
    • 全局注册 :在 mybatis-config.xml 中通过 <typeHandlers> 标签配置;
    • 局部指定 :在 Mapper XML 或注解中通过 typeHandler 属性标记;
  3. 应用转换逻辑:在实体类字段或 SQL 映射中声明使用自定义 TypeHandler。

三、实战:FastJson 实现 JSON 字符串与 List 转换

1. 场景描述

假设数据库表 user_groupusers 字段存储 JSON 字符串,需在 Java 中映射为 List<User> 对象:

sql 复制代码
CREATE TABLE user_group (
    id BIGINT PRIMARY KEY,
    users VARCHAR(2048)  -- 存储格式:[{"id":1,"name":"Alice","age":25},...]
);

2. 实现步骤

① 引入依赖
xml 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>
② 定义 User 实体
java 复制代码
public class User {
    private Long id;
    private String name;
    private Integer age;
    // getters/setters
}
③ 自定义 TypeHandler
java 复制代码
public class ListUserTypeHandler extends BaseTypeHandler<List<User>> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, 
                                   List<User> users, JdbcType jdbcType) throws SQLException {
        ps.setString(i, JSON.toJSONString(users));  // Java→JSON字符串
    }

    @Override
    public List<User> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return parseJson(json);
    }

    private List<User> parseJson(String json) {
        return json == null ? null : 
            JSON.parseObject(json, new TypeReference<List<User>>(){});
    }
    // 其他重写方法略...
}
④ 全局注册 TypeHandler
xml 复制代码
<!-- mybatis-config.xml -->
<typeHandlers>
    <typeHandler handler="com.example.ListUserTypeHandler" 
                javaType="java.util.List" jdbcType="VARCHAR"/>
</typeHandlers>
⑤ 实体类与 Mapper 映射
java 复制代码
public class UserGroup {
    private Long id;
    @TableField(typeHandler = ListUserTypeHandler.class)
    private List<User> users;
    // getters/setters
}
xml 复制代码
<!-- UserGroupMapper.xml -->
<select id="selectUserGroup" resultType="UserGroup">
    SELECT * FROM user_group WHERE id = #{id}
</select>

四、测试与验证

java 复制代码
UserGroup group = sqlSession.selectOne("selectUserGroup", 1L);
System.out.println(group.getUsers()); 
// 输出:[User{id=1, name='Alice', age=25}, User{id=2, name='Bob', age=30}]

五、总结与扩展

  1. 优势

    • 解耦业务与持久化逻辑:将类型转换代码集中管理,提升可维护性;
    • 支持复杂场景:通过自定义逻辑处理加密数据、多语言字段等特殊需求。
  2. 扩展方向

    • 泛型支持 :抽象通用 JSON TypeHandler,通过 TypeReference 适配不同泛型类;
    • 性能优化:针对高频转换类型缓存解析结果,减少重复计算。

通过合理使用 TypeHandler,开发者可以显著提升 MyBatis 在处理复杂数据类型时的灵活性与代码整洁度,是高效 ORM 实践的重要工具。

相关推荐
ephemerals__1 分钟前
【数据结构进阶】哈希表
数据结构·算法·散列表
.猫的树20 分钟前
Java集合List快速实现重复判断的10种方法深度解析
java·开发语言·list·集合
阿巴~阿巴~34 分钟前
关于回溯算法中的剪枝是否需要for循环的总结归纳
数据结构·c++·算法·深度优先·剪枝
Dovis(誓平步青云)1 小时前
【数据结构】二叉树(门槛极低的系统理解)
c语言·数据结构·算法
kk\n2 小时前
C++ 红黑树万字详解(含模拟实现(两种版本))
数据结构·c++
虎鲸不是鱼2 小时前
【全栈开发】从0开始搭建一个图书管理系统【一】框架搭建
java·spring boot·spring·maven·mybatis
郑州吴彦祖7723 小时前
排序算法漫游:从冒泡到堆排的底层逻辑与性能厮杀
java·数据结构·算法·排序算法
张胤尘3 小时前
算法每日一练 (6)
数据结构·算法
转调4 小时前
C++-第十三章:红黑树
数据结构·c++
&星辰入梦来&4 小时前
数据结构秘籍(一)线性数据结构
数据结构