MyBatis本身不处理MySQL日期格式化,真正起作用的是SQL中的DATE_FORMAT()、Java类型转换策略或MyBatis-Plus链式工具;DATE_FORMAT返回字符串,必须映射到String字段,否则抛ClassCastException;查某天记录应改用范围查询而非字符串匹配以保障索引和精度。

MyBatis 本身不处理 MySQL 的日期格式化逻辑,它只负责参数绑定和结果映射;真正起作用的是你写的 SQL(尤其是 DATE_FORMAT())、Java 端的类型转换策略,或 MyBatis-Plus 提供的链式工具。直接在 XML 或 LambdaQueryChainWrapper 中硬拼字符串格式容易出错,也难维护。
MySQL 层用 DATE_FORMAT() 做查询/返回格式化
这是最常用、也最可控的方式:把格式化交给数据库执行,避免 Java 端时区/精度/线程安全等问题。
-
DATE_FORMAT(create_time, '%Y-%m-%d')返回字符串,不能直接映射到Date或LocalDateTime字段——必须对应 String 类型属性,否则会抛ClassCastException - 如果想查“某天的所有记录”,别用
=比较字符串,改用范围查询:create_time >= '2026-06-17 00:00:00' AND create_time < '2026-06-18 00:00:00',更可靠且能走索引 - XML 中写法示例:
<select id="selectByDate" resultType="map"> SELECT id, name, DATE_FORMAT(create_time, '%Y-%m-%d %H:%i:%s') AS formatted_time FROM user WHERE DATE_FORMAT(create_time, '%Y-%m-%d') = #{dateStr} </select>注意:#{dateStr}是传入的"2026-06-17"字符串,不是 Date 对象
MyBatis-Plus 的 LambdaQueryChainWrapper 中避免字符串拼接
很多人用 .apply("DATE_FORMAT(create_time, '%Y-%m-%d') = '" + day + "'"),这属于 SQL 注入高危写法,且无法预编译。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 正确做法是用
apply的参数占位:.apply("DATE_FORMAT(create_time, '%Y-%m-%d') = ?", day),MyBatis-Plus 会自动做参数绑定 - 但注意:
apply不校验字段名,拼错函数名(如写成DATA_FORMAT)会在运行时报 MySQL 错误FUNCTION xxx does not exist - 如果要用日期范围而非字符串匹配,优先用
ge()/lt():.ge("create_time", start).lt("create_time", end),语义清晰且安全
Java 实体类时间字段类型与 JSON 序列化冲突
常见现象:接口返回的 create_time 是时间戳或 ISO 格式,不是想要的 "yyyy-MM-dd HH:mm:ss" —— 这和 MyBatis 无关,是 Jackson/Fastjson 的序列化行为。
- Spring Boot 默认用 Jackson,
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")必须加在 getter 或字段上,且确保spring.jackson.date-format和spring.jackson.serialization.write-dates-as-timestamps=false已配置 - 若项目用了 Fastjson,得换用
@JSONField(format = "yyyy-MM-dd HH:mm:ss"),并确认依赖是com.alibaba.fastjson而非net.minidev.json(后者不识别该注解) - 实体字段类型建议统一用
LocalDateTime(非Date),配合 MyBatis-Plus 的默认 TypeHandler 自动处理,避免时区隐式转换
真正容易被忽略的点是:MySQL 的 DATE_FORMAT() 返回字符串,而 Java 实体字段是时间类型——这种类型错配不会报编译错误,但运行时要么为 null,要么抛异常,且日志里往往只显示 “result map failed”,得翻 MyBatis 日志开 debug 级别才能看到具体字段映射失败原因。

















