web-dev-qa-db-ja.com

Java InstantをMySQLデータベースに保存する方法

Java Dateオブジェクトを使用する最も簡単な方法は、それらをMySql DateTimeオブジェクト(UTC)として保存することでした。Instantに切り替えると、MySQL DateTimeが提供しないため、このアプローチは機能しなくなります。ナノ秒を格納する精度。それらを切り捨てるだけで、新しく作成されたInstantオブジェクトとデータベースから読み取られたオブジェクトとの間で予期しない比較結果が生じる可能性があります。

BigDecimalタイムスタンプはエレガントな解決策として私を驚かせません:タイムスタンプを読みやすくするためにどこでも変換する必要があるため、選択クエリを手動で書くことはより困難になり、Javaでの処理はやや不格好ですInstantまたはLong値にさえ。

ここに行くための最良の方法は何ですか?おそらくvarcharではないでしょう?

8
NotX

マイクロ秒に切り捨てます

明らかに、Instantのナノ秒の解像度をMySQLデータ型DateTimeおよびTimestampのマイクロ秒の解像度に圧縮することはできません。

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 ) ;

…そして…

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

次に、比較します。

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

データベースから引き出された値が元の値と一致しないことを賢明に心配します。 1つの解決策は、ビジネス上の問題に受け入れられる場合、元のデータのナノ秒をマイクロ秒に切り捨てることです。私は一般的にこのアプローチをお勧めします。

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

現在、データにナノ秒が含まれている可能性は低いため、このアプローチで十分です。今日の主流のコンピューターは、私が知る限り、ナノ秒をキャプチャできるハードウェアクロックを備えていません。

エポックから数える

存在する可能性のあるナノ秒データを失う余裕がない場合は、Count-from-Epochを使用してください。

私は通常、エポック基準日からのカウントとして日時を追跡しないことをお勧めします。ただし、マイクロ秒ベースの値に限定されたMySQLやPostgresなどのデータベースにナノ秒ベースの値を格納する方法は他にほとんどありません。

整数のペアを格納します

1970-01-01T00:00Zなどのエポック以降、非常に多くのナノ秒を使用するのではなく、Instantクラスの内部で採用されているアプローチに従うことをお勧めします。pairを使用します。 =数字の。

whole秒の数を整数としてデータベースに保存します。 2番目の列には、小数秒のナノ秒数を整数として格納します。

これらの数値は、Instantオブジェクトから/に簡単に抽出/挿入できます。単純な64ビットのlong番号のみが含まれます。 BigDecimalまたはBigIntegerは必要ありません。 2つの数値の少なくとも1つに32ビット整数列を使用できる可能性があると思います。ただし、単純にするため、およびJava.time.Instantクラスのlongのペアと直接互換性があるために64ビット整数列タイプを選択します。

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

…そして…

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

時系列で並べ替える場合は、マルチレベルの並べ替えを行う必要があります。最初に秒全体の列で並べ替え、次にナノ秒の秒の小数列で次に並べ替えます。

3
Basil Bourque