前两天,我们的生产环境上出现"### Error querying database. Cause: java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp"异常。
虽经处理,但一直不知为什么会产生0000-00-00 00:00:00的数据,所以特重现并看如何产生的。
一.解决办法 连接数据库转化为对象出错的解决办法为在数据库连接后面加上参数zeroDateTimeBehavior=convertToNull 这样如果碰到 ‘0000-00-00:00:00:00’的日期类型时,将会转化为null值
db.jdbcurl=jdbc:mysql://192.168.1.52:3306/db?zeroDateTimeBehavior=convertToNull
二.原因分析
-- Create a table named 'User'
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`address` varchar(200) DEFAULT NULL,
-- `update_time` timestamp NULL DEFAULT NULL,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
-- Insert a test record
Insert INTO `user` VALUES ('1', 'bijian', '120', 'shengzhen,shengzhenwang', current_timestamp());
1.数据库服务模式
针对数据插入数据‘0000-00-00:00:00:00’ 数据本身不接受的解决办法为,用root用户登录,重新设置数据库的模式(尽量使用root用户 要不然 GLOBAL设置不成功,但是可以设置SESSION的),具体可以参考:mysql SQL服务器模式。
简来来讲,就是查看数据库现有的服务模式是否控制允许插入‘0000-00-00:00:00:00’这种非正常的数据。
/**
* 没有NO_ZERO_IN_DATE,NO_ZERO_DATE,能正常设置'0000-00-00 00:00:00'
*/
select @@sql_mode;
SET SESSION sql_mode = 'STRICT_TRANS_TABLES';
SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
Insert INTO `user`(id, name, age, address, update_time) VALUES ('5', 'bijian', '120', 'shengzhen,shengzhenwang', '0000-00-00 00:00:00');
/* * NO_ZERO_IN_DATE,NO_ZERO_DATE加上,然后重新设置
*/
SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_ZERO_IN_DATE,NO_ZERO_DATE';
-- Error Code: 1292. Incorrect datetime value: '0000-00-00 00:00:00' for column 'update_time' at row 1 0.016 sec
2.IGNORE选项
如果数据库服务模式中有NO_ZERO_IN_DATE,NO_ZERO_DATE,其实也能通过IGNORE选项新增,只是有一个告警而已。
-- update_time字段值为 0000-00-00 00:00:00,新增成功,但有告警 1 warning(s): 1264 Out of range value for column 'update_time' at row 1 0.000 sec
Insert ignore INTO `user` VALUES ('2', 'bijian', '120', 'shengzhen,shengzhenwang', '1970-01-01 00:00:01');
-- update_time字段值为 0000-00-00 00:00:00
Insert INTO `user` VALUES ('3', 'bijian', '120', 'shengzhen,shengzhenwang', '0000-00-00 00:00:00');
3.时区time_zone
非正常时间值,timestamp新增的值和time_zone有关。如果time_zone是'+8:00',则新增的非正常的日期会转换成‘0000-00-00:00:00:00’入库,而如果time_zone是'+0:00',则会原封不动地入库。
/*
* 非正常时间值,timestamp新增的值和time_zone有关
*/
set time_zone='+8:00';
show variables like '%time_zone%';
-- select now()来验证时区
select now();
-- update_time字段值为 0000-00-00 00:00:00
set time_zone = '+0:00';
show variables like '%time_zone%';
-- select now()来验证时区
select now();
-- update_time字段值为 1970-01-01 00:00:01
Insert ignore INTO `user` VALUES ('14', 'bijian', '120', 'shengzhen,shengzhenwang', '1970-01-01 00:00:01');
|