执行 SQL 或读取结果时出现下面的错误,首先要查清谁在把字符串转换成时间戳:
java.lang.IllegalArgumentException:
Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
一次旧项目排查中,数据库字段为 char(8),实体却按 Date 映射。这是值得检查的类型契约,但还要沿调用栈确认转换发生在驱动、ORM、类型处理器还是业务代码里。
八位日期不是 JDBC 时间戳
Timestamp.valueOf(String) 接收 JDBC 时间戳格式,包含日期和时间,例如:
java.sql.Timestamp value =
java.sql.Timestamp.valueOf("2018-08-06 10:36:38");
它不是任意日期字符串的自动识别器。若实际文本是 20180806,就不能因为“看起来是日期”直接按同一方法解析。Java 8 Timestamp
日期、时间戳和某一确定时刻也不是一回事。缺少时间或时区的值,不应只为让转换通过就随意补成零点。
先明确 char(8) 的业务格式
假设接口明确约定八位文本是 uuuuMMdd,可以在 Java 8 的输入或类型映射边界做严格转换:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;
DateTimeFormatter format = DateTimeFormatter
.ofPattern("uuuuMMdd")
.withResolverStyle(ResolverStyle.STRICT);
LocalDate date = LocalDate.parse("20180806", format);
这是格式示例,不是恢复出的真实数据库样本。应事先约定 null、空白、全零和非法日期如何处理;不能靠宽松解析把不存在的日期悄悄调整成另一天。日期格式与解析规则
在映射处显式连接两种类型
如果数据库暂时必须保留字符字段,可以先读取字符串,再按约定转换为业务日期;写回时使用同一格式。使用 ORM 时把规则放在明确的转换器或 TypeHandler 中,并测试读写往返。
如果字段本来表示 SQL DATE,可按项目 JDBC/驱动能力选择对应日期映射,而不是让字符列伪装为时间戳。迁移数据库字段前,应先检查历史脏值、索引、查询条件和回退方案,不直接在生产执行 DDL。
至少覆盖合法日期、空值、空白、格式错误和不存在日期。只有“Java 类型名称与数据库类型看起来相近”,还不足以证明转换契约正确。