10

使用 JavaDate对象最简单的方法是将它们存储为 MySqlDateTime对象(以 UTC 格式)。切换到Instant这种方法将不再起作用,因为 MySQLDateTime不提供存储纳秒的精度。仅仅截断它们可能会导致新创建Instant的对象与从数据库中读取的对象之间出现意外的比较结果。

BigDecimal时间戳并不是一个优雅的解决方案让我印象深刻:手动编写选择查询变得更加困难,因为您必须在各处转换时间戳以使其可读,并且与值Instant甚至Long值相比,Java 中的处理有些笨拙。

去这里的最佳方式是什么?应该不会varchar吧?

4

1 回答 1

8

截断到微秒

显然,我们不能将 a 的纳秒分辨率压缩到MySQL 数据类型Instant微秒分辨率.DateTimeTimestamp

虽然我不使用 MySQL,但我想JDBC 驱动程序被构建为在接收时忽略纳秒Instant,将值截断为微秒。我建议你尝试一个实验来看看,也许检查你的驱动程序的源代码是否符合 JDBC 4.2 及更高版本。

Instant instant = Instant.now().with( ChronoField.NANO_OF_SECOND , 123_456_789L ) ;  //Set the fractional second to a spefic number of nanoseconds.
myPreparedStatement.setObject( … , instant ) ;

……和……</p>

Instant instant2 = myResultSet.getObject( … , Instant.class ) ;

JDBC 4.2 规范需要支持但奇怪的OffsetDateTime是不需要两种更常用的类型,Instant以及ZonedDateTime. 如果您的JDBC 驱动程序不支持Instant,请转换。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;  // Use `OffsetDateTime` if your JDBC driver does not support `Instant`. 
Instant instant2 = odt.toInstant() ;  // Convert from `OffsetDateTime` to `Instant`. 

然后比较。

Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;

您明智地担心从数据库中提取的值与原始值不匹配。如果您的业务问题可以接受,一种解决方案是将原始数据中的任何纳秒级截断为微秒级。我一般推荐这种方法。

java.time类提供了一种方法truncatedTo。传递一个ChronoUnit枚举对象来指定粒度。在这种情况下,那将是ChronoUnit.MICROS.

Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;

目前这种方法应该足够了,因为您的数据中不太可能有任何纳秒。据我所知,今天的主流计算机不具备能够捕获纳秒的硬件时钟。

从纪元开始计数

如果您无法承受丢失任何可能存在的纳秒级数据,请使用从纪元开始计数。

我通常建议不要将日期时间作为从纪元参考日期开始的计数。但是,您几乎没有其他选择将基于纳秒的值存储在数据库中,例如 MySQL 和 Postgres,仅限于基于微秒的值。

存储整数对

我建议不要使用自 1970-01-01T00:00Z 之类的纪元以来的大量纳秒,我建议遵循Instant类内部采用的方法:使用一数字。

秒数作为整数存储在数据库中。在第二列中,将小数秒中的纳秒数存储为整数。

您可以轻松地从对象中提取/注入这些数字Instant。只涉及简单的 64 位long数字;不需要BigDecimalor BigInteger。我想您也许可以对这两个数字中的至少一个使用 32 位整数列。但为了简单起见,我会选择 64 位整数列类型,并与java.time.Instant类的 long 对直接兼容。

long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;

……和……</p>

Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;

按时间顺序排序时,您需要进行多级排序,首先在整个 seconds 列上排序,然后在 nanos fraction-of-second 列上进行第二次排序。

于 2017-11-10T16:06:37.243 回答