【问题标题】:ZonedDateTime persistance to SQL DatabaseZonedDateTime 持久性到 SQL 数据库
【发布时间】:2017-06-09 20:44:24
【问题描述】:

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

  1. 在 DB(当前为 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);

它返回错误(我需要在我的域模型的覆盖相等方法中比较它们)
以下是两者的打印结果:

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

问题:

  1. 我的选择是否正确。也许,我应该使用其他列或 java 类型...
  2. 我进行转换是否正确。也许还有其他更好的方法

谢谢

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

【问题讨论】:

  • 撇开小数秒问题不谈,为什么不使用Instant 将时间戳存储为UTC?
  • 我刚做的一大早,虽然有疑问。你用你的问题把它们抹掉了,谢谢。我不想编辑我的答案,因为它不会影响分数行为,并且仍然想查看其他关于类型的命题,例如,就像你写的那样。

标签: java mysql time timezone zoneddatetime


【解决方案1】:

看了这篇文章和cmets,我终于知道是什么问题了:

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

【讨论】:

  • 这是一个很棒的发现。感谢分享!一定要接受你自己的答案(一旦 48 小时过去了它应该让你)。
【解决方案2】:

MySQL 在 5.6.4 版本中增加了对小数秒的支持。我的猜测是你正在运行比这更早的东西,因此你的毫秒被截断了。

来自 MySQL 5.6 文档:

在 MySQL 5.6.4 之前,实例受到限制,其中时间值中允许小数秒部分。在诸如文字值之类的上下文中,以及某些时间函数的参数或返回值中,尾随小数部分是允许的。 ...但是,当 MySQL 将值存储到任何时间数据类型的列中时,它会丢弃任何小数部分并且不存储它

MySQL 5.6.4 及更高版本扩展了对TIMEDATETIMETIMESTAMP 值的小数秒支持,精度高达微秒(6 位)。 ...

如果您愿意,可以比较此文档中版本 5.55.65.7 的更改。

【讨论】:

  • 不,我使用 MariaDB 10.1.20(是的,关于我的数据库,我有点不准确)无论如何,MariaDB 包含自 5.3 以来的分数,比 MySQL 早几个月。
  • 哦,好的。请将其添加到问题中,我将删除它。
  • 别担心,我很感激任何答案。此外,也许你可以帮助我关于我的选择?我做对了吗?我的意思是类型?
  • TIMESTAMP 是一个不错的选择,当然。只要您只关心坚持Instant。如果您想要整个 ZonedDateTime 包括时区,则必须将时区 ID 保存到单独的字段中。
  • 谢谢。我终于有了一个想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-19
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
  • 2018-01-16
  • 2015-12-23
相关资源
最近更新 更多