升级mysql-connector-java中timestamp的坑

xiaoxiao2021-02-28  28

现象:

connector在5.1.23版本后,java.util.Date的数据中小数秒会被拼接到sql中,导致更新、查询中timestamp用在where条件找不到存在的数据。

问题复盘:

我们项目中之前用到的connector版本是5.1.21,需要升级到5.1.32。昨天升级后发布一台机器发现了报错。报错的方法是完成生成派单(F单insert),然后更新该派单的rootid(F单update)的功能。我们在noah环境上复现了问题,并打开了mybatis输出sql语句的开关,发现输出的派单订单表f_n_order_info中的last_updated字段输出格式为:2017-11-29 16:41:31.088。 FOrderInfo实体类中lastUpdated字段的类型为java.util.Date。

/** * 最后更新时间 */ private Date lastUpdated;

mysql中f_n_order_info表中last_updated字段为TimeStamp类型。 last_updated timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP` COMMENT ‘最后更新时间’ 出问题的update语句:

update f_n_order_info set last_updated = now(),root_id = id where id = #{orderId} and last_updated = #{lastUpdated}

查看输出的sql语句日志发现,mybatis输出的sql语句中,无论insert 还是update 中last_updated就是带有小数秒的格式。看似应该没有问题,况且之前21版本是好的,32版本出问题了。所以我们断定是connector版本进行了修改。

问题原因:

查看了connector官方版本修改文档,里面一个5.1.23版本中一个bugfix引起了我们的注意。 The nativeSQL() method would always truncate fractional seconds rather than preserving the fractional part in the output string. Now Connector/J checks the server version: it preserves the fractional part for MySQL 5.6.4 and greater, and truncates the fractional part for older versions. (Bug #14748459, Bug #60598) 参考文档:https://docs.oracle.com/cd/E17952_01/connector-j-relnotes-en/connector-j-relnotes-en.pdf

大意是修改了nativeSQL方法,之前对于时间的做法是截断了小数秒,现在5.6.4版本后保留这个小数秒(也就是说之前connector在拼接sql的时候就直接屏蔽掉了小数秒,在23版本开始这个小数秒要加回来)。insert的时候,我们的字段timestamp没有精度,所以即使我们传入形如2017-11-29 16:41:31.088的数据,mysql只会读取年月日时分秒,而不会保存这个小数秒。正如前面所说21版本之前,connector直接截断了这个小数秒,所以我们的update语句不会出现更新不到的问题。但是23版本以后,connector会带上我们传入的小数秒,那么update语句的where条件中时间就是带有小数秒的,这就相当于用2017-11-29 16:41:31.088去匹配2017-11-29 16:41:31的数据,所以不成功。

问题解决方案:

我们这边初步有两个方案,一个是把update语句中这个过滤条件删除掉,因为这个语句已经有了主键进行更新,不需要这个字段作为辅助条件,而且经过分析,这个业务也不需要乐观锁来避免覆盖,这个方法对于我们修改成本低。第二个就是每次传入Date前,把时间进行格式化,屏蔽掉小数秒,这样查询的时候就不会因为不匹配找不到数据。

反思:

建表的时间字段,个人推荐使用bigint来保存时间戳,这样方便保存也方便查询,也不会被时区等让人头疼的问题烦心。

相关connector5.1.23修改的时间部分代码,可以参考com.mysql.jdbc.EscapeProcessor#processTimeToken这个类中的方法,比对不同版本的差异。

转载请注明原文地址: https://www.6miu.com/read-850053.html

最新回复(0)