MyBatis中resultMap日期映射失败主因是未显式配置匹配的typeHandler与jdbcType。需为每个日期字段指定对应处理器(如LocalDateTimeTypeHandler),且Java类型、jdbcType、typeHandler三者必须严格一致;XML中pattern属性无效,自定义格式需继承BaseTypeHandler并处理null;MyBatis-Plus场景下自动映射可能绕过XML配置,需启用autoResultMap或禁用自动映射。

MyBatis 中 resultMap 日期字段映射失败的常见原因
MyBatis 默认用 java.util.Date 解析 XML 中的字符串,但若数据库字段是 TIMESTAMP 或 DATE,而 XML 里写的是 "2024-03-15" 或 "2024-03-15 14:23:05",就容易抛 org.apache.ibatis.executor.result.ResultMapException —— 根本没触发类型转换逻辑,因为 MyBatis 没找到匹配的 TypeHandler。
关键点:MyBatis 不会自动根据字段名或 JDBC 类型推断日期格式;它只看配置的 jdbcType 和注册的 TypeHandler。
- 数据库列是
DATE,XML 中填"2024-03-15 14:23:05"→ 解析失败(时分秒多余) - 字段声明为
java.time.LocalDateTime,但没配对应TypeHandler→ 反射失败或空值 - 用了
@Select注解但没加resultMap,导致忽略 XML 中的typeHandler配置
在 resultMap 中显式指定 typeHandler
必须为每个日期/时间字段单独指定处理器,不能靠全局默认。MyBatis 3.4+ 原生支持 java.time.*,但需显式声明,否则仍走老的 java.util.Date 路径。
示例:映射 PostgreSQL 的 timestamptz 到 OffsetDateTime
-
jdbcType必须与数据库实际类型对齐(如 Oracle 用TIMESTAMP,MySQL 8.0+ 用TIME或TIMESTAMP) - Java 类型和
typeHandler必须严格匹配:LocalDateTime→LocalDateTimeTypeHandler,ZonedDateTime→ 自定义(原生不支持) - 若用 Lombok 的
@Data,确保日期字段 getter/setter 可访问,否则typeHandler不生效
自定义 TypeHandler 处理非标准格式(如 "yyyy-MM-dd HH:mm:ss.SSS"
当数据库返回字符串(比如通过 CONCAT 拼接的时间),或前端传入固定格式字符串需入库时,必须写自定义处理器。MyBatis 不解析 pattern 属性,XML 里写 pattern="yyyy-MM-dd" 是无效的。
示例:处理带毫秒的字符串转 LocalDateTime
public class CustomLocalDateTimeTypeHandler extends BaseTypeHandler{ private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); @Override public void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType) { ps.setTimestamp(i, Timestamp.valueOf(parameter)); } @Override public LocalDateTime getNullableResult(ResultSet rs, String columnName) { String str = rs.getString(columnName); return str == null ? null : LocalDateTime.parse(str, FORMATTER); } }
- 注册方式:在 MyBatis 配置中用
- XML 中引用:
typeHandler="xxx.CustomLocalDateTimeTypeHandler" - 注意空值处理:数据库字段为 NULL 时,
rs.getString()返回null,必须判空,否则parse抛NullPointerException
Spring Boot + MyBatis-Plus 场景下 XML 映射的兼容陷阱
如果项目已引入 MyBatis-Plus,它的自动填充、逻辑删除等功能会绕过 XML 的 resultMap,直接走反射赋值。此时即使 XML 写了 typeHandler,也可能被跳过。
- 启用
configuration.mapUnderscoreToCamelCase=true后,create_time自动映射到createTime,但不会触发你写的typeHandler - 使用
@TableName(autoResultMap = true)才会让 MP 尝试读取同名 XML 的resultMap,否则默认用内置映射 - MP 的
MetaObjectHandler中若对日期字段做setFieldValByName("updateTime", LocalDateTime.now(), metaObject),传入的是对象,不是字符串,不经过 XML 解析流程
真正需要 XML 控制格式转换的场景,建议关闭 MP 的自动映射,显式调用 selectList(wrapper).get(0) 并确保 SQL 指向带 resultMap 的语句。










