ZonedDateTime 持久化到 SQL 数据库

ZonedDateTime persistance to SQL Database

美好的一天,
我创建了将在全球范围内使用的 Web 应用程序服务。
因此,我需要以 UTC 格式存储日期时间值,并以墙上的时钟向最终用户表示它们。
阅读 Stack overflow 后,我明白了,我应该:

  1. 在数据库中使用时间戳作为列类型(当前为 MariaDB 10.1.20)
  2. 在Java中使用ZonedDateTime(我使用java8)

在这些值之间进行转换时出现问题。
当我使用 JDBC 时,我必须进行以下转换:

java.sql.Timestamp <-> java.time.ZonedDateTime 

我的代码:

// Get current zonedDateTime
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneOffset.UTC);

// Convert zonedDateTime to java.sql.Timestamp before saving to DB
Timestamp = Timestamp.from(zonedDateTime.toInstant());

// Get zonedDateTime from resultSet
Timestamp timestamp = (Timestamp) resultSet.getObject("created");
ZonedDateTime zonedDateTime = 
    ZonedDateTime.ofInstant(ts.toInstant(), ZoneOffset.UTC))

当我使用:

zonedDateTimeBeforeSave.isEqual(zonedDateTimeAfterSave);

它 returns 我错了(我需要在我的域模型的重写相等方法中比较它们)
下面是两者的打印:

zonedDateTimeBeforeSave: 2017-01-24T20:18:17.720Z
zonedDateTimeAfterSave: 2017-01-24T20:18:17Z

问题:

  1. 我的选择对吗?也许,我应该使用另一列或 java 类型...
  2. 我做的转换对吗?也许还有其他更好的方法

谢谢

  1. 编辑: 在马特约翰逊的帮助下,我明白问题出在事实上,当我将日期时间保存到数据库时,它不会保存分数,尽管它应该。仅供参考列类型是 timestamp(6).
  2. 编辑: 现在我使用 java.time.Instant 而不是 ZonedDateTime

MySQL 在 5.6.4 版中添加了对小数秒的支持。我猜你 运行 比那年长,因此你的毫秒数被截断了。

来自 MySQL 5.6 文档:

Before MySQL 5.6.4, the instances are limited in which a fractional seconds part is permitted in temporal values. A trailing fractional part is permissible in contexts such as literal values, and in the arguments to or return values from some temporal functions. ... However, when MySQL stores a value into a column of any temporal data type, it discards any fractional part and does not store it.

MySQL 5.6.4 and up expands fractional seconds support for TIME, DATETIME, and TIMESTAMP values, with up to microseconds (6 digits) precision. ...

如果您愿意,请比较此文档与版本 5.5, 5.6, and 5.7 的变化。

看完这篇post和评论后,我终于找到了问题所在:

http://mysqlnoob.blogspot.com/2016/09/replication-from-mysql-56-to-mariadb-10-fails-with-fractional-seconds.html

原因是我的 MariaDB JDBC 驱动程序
我有一个旧的 1.1.7 版本,参数 "useFractionalSeconds" 设置为 false。
解决方案是将此参数设置为 true (f.ex by URL) 或更新驱动程序。目前最新版本为 1.5.7 至 25.01.2017