TIMESTAMP类型‘0000-00-00 00:00:00’值转换报错问题

总结一下之前在开发中遇到的一个小BUG。。

在数据库开发中,为业务新增了表,设计表的时候未给表的创建时间字段和更新时间字段设置默认值。当然我没有设置,那么导致出现了这样一个的问题,就是我在插入记录的时候,由于没有指定默认值,MySQL会给TIMESTAMP类型字段默认一个‘0000-00-00 00:00:00’,然后在通过JDBC转换成java.sql.Timestamp的时候报了这样一个错:

java.sql.SQLException: Cannot convert value '0000-00-00 00:00:00' from column 1 to TIMESTAMP.

 分析原因:首先我们知道MySQL中TIMESTAMP支持的时间范围为19700101080001到2038年的某个时间,但是当插入的值超出了取值范围,MySQL认为该值溢出,会使用‘0000-00-00 00:00:00’进行填补,所以TIMESTAMP存‘0000-00-00 00:00:00’是没问题的。

 而真正的原因我们可以在MySQL中找到:https://bugs.mysql.com/bug.php?id=19274

不难发现 JDBC 默认最小时间 为 ‘0001-01-01 00:00:00’ ,而‘0000-00-00 00:00:00’ 在MySQL中也只是作为一个特殊值存在的,自然转换时就会报错

因此官方提供了我们解决策略:

在JDBC连接串中有一项属性:zeroDateTimeBehavior,可以用来配置出现这种情况时的处理策略,该属性有下列三个属性值:
l exception:默认值,即抛出SQL state [S1009]. Cannot convert value....的异常;
l convertToNull:将日期转换成NULL值;
l round:替换成最近的日期即0001-01-01;
因此对于这类异常,可以考虑通过修改连接串,附加zeroDateTimeBehavior=convertToNull属性的方式予以规避。


总结解决方式:

1、在设计表的时候加入默认值(避免存入‘0000-00-00 00:00:00’)

`createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间'

这样的话,在新增记录的时候就不会导致记录里存在一条时间值为‘0000-00-00 00:00:00’的记录,因为java.sql.Timestamp本身不支持该值,所以不存在我们主动赋值的情况,业务上也没有这个需求。。当然手动MySQL insert这样一条记录除外。。。

2、在JDBC的url加上zeroDateTimeBehavior参数:

以application.yml为例,在配置datasource的时候其中url可以配置如下

jdbc:mysql://localhost:3306/pe?useUnicode=true&characterEncoding=gbk&zeroDateTimeBehavior=convertToNull 

这样JDBC转换时就会将零值转成NULL

或者

jdbc:mysql://localhost:3306/pe?useUnicode=true&characterEncoding=gbk&zeroDateTimeBehavior=round

 这样JDBC转换时就会将零值转成‘0001-01-01 00:00:00’

以上就是两种解决方式,当然还是推荐第一种。

你可能感兴趣的:(SQL,MySQL,JDBC,MySQL)