MyBatis 中自定义 typeHandler 不生效,需全局注册并显式声明于 resultMap;#{} 支持类型转换,${} 仅字符串拼接;JSON/LocalDateTime 等需专用 TypeHandler;嵌套 resultMap 中 typeHandler 需单独指定,且必须双向实现。

MyBatis 中 resultMap 的 typeHandler 不生效?检查注册方式和作用域
MyBatis 默认对基本类型(String、Integer、Date)有内置 TypeHandler,但自定义类型(如枚举、LocalDateTime、JSON 字符串转对象)必须显式绑定,否则会报 Cannot convert value of type 'java.lang.String' to required type 或字段为 null。
常见错误是只在 resultMap 里写了 typeHandler 属性,却没在全局或映射语句中真正启用:
-
resultMap中的仅对当前字段生效,但前提是该TypeHandler已被 MyBatis 加载(即已注册) - 未注册的
TypeHandler会被静默忽略,不会报错,只返回null - 推荐在
mybatis-config.xml中全局注册: - 若用 Spring Boot + MyBatis-Plus,改用
@Configuration类中注册Configuration.addTypeHandler(...)
XML 中 #{} 和 ${} 对数据类型的影响完全不同
#{} 是预编译参数占位符,MyBatis 会根据字段类型自动选择 TypeHandler;${} 是字符串拼接,绕过所有类型转换逻辑,直接转成 String 后拼入 SQL —— 这是多数“类型丢失”的根源。
例如传入 LocalDateTime:
-
WHERE create_time > #{startTime}→ 正确:MyBatis 调用LocalDateTimeTypeHandler,生成带时区的 JDBC 参数 -
WHERE create_time > '${startTime}'→ 错误:调用toString(),结果可能是"2024-05-20T14:30:00",数据库报语法错误或隐式转换失败 -
ORDER BY ${sortField}属于合法动态列名场景,但绝不能用于值参数
PostgreSQL / MySQL 的 jsonb / JSON 字段在 XML 映射中需要专用 TypeHandler
数据库原生 JSON 类型无法被 MyBatis 默认处理,直接映射到 String 会丢失结构,映射到 Object 则抛 ClassCastException。
本文档主要讲述的是mybatis语法和介绍;MyBatis 是一个可以自定义SQL、存储过程和高级映射的持久层框架。MyBatis 摒除了大部分的JDBC代码、手工设置参数和结果集重获。MyBatis 只使用简单的XML 和注解来配置和映射基本数据类型、Map 接口和POJO 到数据库记录。相对Hibernate和Apache OJB等“一站式”ORM解决方案而言,Mybatis 是一种“半自动化”的ORM实现。感兴趣的朋友可
必须使用第三方 TypeHandler,例如 Jackson:
- Maven 引入:
com.fasterxml.jackson.core:jackson-databind和org.mybatis:mybatis-typehandlers-jsr310(后者仅支持 JSR310 时间类型,不支持 JSON) - 自定义
JsonTypeHandler,重写setNonNullParameter和getNullableResult,内部用ObjectMapper序列化/反序列化 - 在
resultMap中指定: - 注意:MySQL 8.0+ 的
JSON类型需 JDBC 驱动开启allowPublicKeyRetrieval=true才能读取二进制 JSON 值,否则返回空
嵌套 resultMap 时子映射的 typeHandler 容易被父级覆盖
当主 resultMap 引用另一个 resultMap(如 ),子映射中声明的 typeHandler 可能被忽略——MyBatis 优先使用父级 resultMap 的类型推导逻辑。
解决方法很直接:
- 不要依赖嵌套映射自动继承
typeHandler,每个字段都显式声明typeHandler - 若子对象字段类型与数据库列类型不一致(如 DB 存
VARCHAR,Java 期望Enum),必须在子resultMap的中写死typeHandler - 避免用
autoMapping="true",它会跳过所有手动配置的typeHandler
最常被忽略的一点:TypeHandler 必须同时实现 setParameter(写入)和 getResult(读取),缺一不可;只重写一半会导致单向转换失败,现象是插入正常、查询为 null。









