问题情景
在 Java 代码中使用 new Date()
赋值日期,存储到数据库 DATETIME
字段后,在数据库中多了一秒,经过排查是数据库对Java Date 值进行了四舍五入,导致此问题。
问题剖析
Java 的 java.util.Date
类时间精确度到毫秒(milliseconds),MySQl 中的日期时间类 TIME
、DATETIME
、TIMESTAMP
最大可以支持 6 位,即精确到毫秒(microseconds),以格式 type_name(fsp)
格式进行定义,如 DATETIME(3)
为定义精确到秒后 3 位(毫秒)。当不指定 fsp
的时候,默认值为 0,即最大精确度保留到秒。
此问题场景下,MySQL 的 DATETIME
未指定精确度,最大精确度为秒,而 java.util.Date
精确度为毫秒,MySQl会对末尾的时间进行四舍五入,当毫秒值大于 500 时,便会进 1 位增加一秒,造成了此问题。
从 MySQl 8 开始,可以通过启用 TIME_TRUNCATE_FRACTIONAL 参数使用截断模式,即直接移除末尾小数,不进行四舍五入。
测试代码
DROP TABLE IF EXISTS fractest;
CREATE TABLE fractest( c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2) );
INSERT INTO fractest VALUES
('17:51:04.777', '2018-09-08 17:51:04.777', '2018-09-08 17:51:04.777');
INSERT INTO fractest VALUES
('17:51:04.555', '2018-09-08 17:51:04.555', '2018-09-08 17:51:04.555');
INSERT INTO fractest VALUES
('17:51:04.444', '2018-09-08 17:51:04.444', '2018-09-08 17:51:04.444');
SELECT * FROM fractest;
发表回复