前兩天,我們的生產環境上出現"### 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');