MySQL更新日期报错
1. 问题描述
最近在迁移MySQL数据库,版本变化:5.6.26 -> 5.7.28。数据库迁移后,在项目自测中遇到了一个问题,在此记录下。插入一条记录时,报错:
org.springframework.dao.DataIntegrityViolationException:
### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Incorrect datetime value: '1970-01-01 08:00:00.001' for column 'modified_time' at row 1
### The error occurred while setting parameters
### SQL: INSERT INTO table (id, created_time, modified_time) values ( ?, ?, ?)
### Cause: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Incorrect datetime value: '1970-01-01 08:00:00.001' for column 'modified_time' at row 1
; Data truncation: Incorrect datetime value: '1970-01-01 08:00:00.001' for column 'modified_time' at row 1; nested exception is com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Incorrect datetime value: '1970-01-01 08:00:00.001' for column 'modified_time' at row 1
2. 操作
2.1 表结构
CREATE TABLE `table` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键id',
`created_time` timestamp DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`modify_time` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='表名'
一直以来笔者建表的created_time、modify_time都是由MySQL自行维护,在MyBatis语句中都不插入或更新这两个字段,也推荐各位这么操作。
2.2 Java代码
但这次是修改同事的表,在做单元测试的时候就出现了上面的报错。
// 手动设置时间,0纯属随手一输;不输入参数,取当前时间则没有报错
.setCreatedTime(new Date(0));
3. 问题分析
在网上搜索一番后,有各种答案:
- 时间类型由
timestamp
改成datetime
。这种没有看到很具体的原因,而且最主要的是如果已经投产,更改表结构是大忌; - 更新驱动版本。这个对笔者也不适用,生产的MySQL版本是定好的,无法更改。
在多方搜索了,找到了答案,参数范围错误,这点这能说是个坑了,没有什么技术点。放个官网:MySQL5.7时间格式说明。
在官网中有提到,timestamp的取值范围为:‘1970-01-01 00:00:01’ UTC to ‘2038-01-19 03:14:07’ UTC
The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of ‘1970-01-01 00:00:01’ UTC to ‘2038-01-19 03:14:07’ UTC.
因为Java的Date对象,传入参数单位为毫秒,所以必须是大于等于1000,0-999则会报以上错误。
好吧,只是单元测试的时候乱输参数遇到了,所以记录下这个问题,实际开发中也不会传入小于1000的参数。各位旁友如果不适用请略过,可以参考官网链接说明,从中分析查找答案,也有看到其他人是使用datetime设置值范围错误报错的。