7

エンティティに日付フィールドを設定しているときに、奇妙な休止状態に関連する問題が発生しました。日付はJavaプログラムでUTCとして解釈されます(割り当てられた日付が「UTC」にあることを確認するためにSystem.outを実行しました。ただし、Hibernateが実際にデータベースに保持されると、日付は現地時間に変換されて保存されます)ex 。値はエンティティセッターで「2009-09-0900:08:08」として設定されています-GMTデータベースに保持される実際の値は「2009-09-0808:08:08」-米国東部時間です。どこで、なぜこれが起こっているのか、そしてそれを防ぐ方法を見つけることができません。ありがとう

PS私はjoda日付ライブラリを使用しており、フィールドに@ org.hibernate.annotations.Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime")で注釈を付けています。

4

3 に答える 3

3

ただし、Hibernateが実際にデータベースに保持される場合、日付は現地時間に変換されて保存されます)。値はエンティティセッターで「2009-09-0900:08:08」として設定されています-GMTデータベースに保持される実際の値は「2009-09-0808:08:08」-米国東部時間です。

まず、MySQLに日付を保存するために使用している列タイプ(TIMESTAMPまたはDATETIME)に関係なく、どちらもタイムゾーンを保存しません。Reから:日時を使用したタイムゾーンの保存

  • タイムスタンプは1970年からの秒数で、4バイト単位です。GMTで保存されます。つまり、TZオフセットは、値を格納するときに適用され、値をフェッチするときに再適用されます。(...)

  • DATETIMEは、8バイトの数字列「yyyymmddhhmmss」です。(...)

そして第二に、バグのある動作でない限り、変換はサーバーまたはサーバーのタイムゾーン設定に応じてJDBCドライバーのいずれかによって行われるため、一貫性のないデータが取得されないことを理解しています。

どちらの場合も、私のポイントは、「2009-09-0900:08:08」-GMTまたは「2009-09-0808:08: 08」を保存することです。データベース。

ただし、表示時に別の変換が行われているように見えます。これは疑問を投げかけます:「永続化された日付」の値を実際にどのようにチェックしたのですか。「問題」はSQLクライアントで発生しますか?Javaコードでは?

参考文献


DateTimeのMySQLドキュメントには、「MySQLはDATETIME値を「YYYY-MM-DDHH:MM:SS」形式で取得して表示する」と記載されています。つまり、mysqlは「エポックからのミリ秒」を上記の形式に変換します。だから今私の質問は、タイムゾーン情報もmysqlに保存されていますか?

私は最初の答えを更新しました(これは完全に正確/網羅的ではありませんでした)。DATETIMEまたはTIMESTAMPのどちらを使用していても、答えはノーです。

私が行ったもう1つの観察結果は、上記の日付の「変換」の問題は、ImがJavaアプリケーションで日付を設定している場合にのみ存在するということです。'UTC_TIMESTAMP()'を使用して日付を更新/設定するmysqlトリガーを作成すると、日付は'UTC'時間で表示されます。

UTC_TIMESTAMP ()関数は、常に現在のUTC日付と時刻を返します。


私が知りたいのは:

  • どのようにして問題を「明らかに」しましたか?SQLクライアントまたはJavaから?
  • JVMのローカルタイムゾーンは何ですか?
  • MySQLサーバーのタイムゾーンとは何ですか?
  • MySQL JDBCドライバーのバージョンは何ですか?
  • 生のJDBCを使用してテストを実行できますか?
于 2010-09-07T01:12:12.300 に答える
1

DB(読み取り/書き込み用)で日付をUTCとして扱うために、この小さなオープンソースライブラリを使用できますDbAssistUtcDateTypeエンティティ内のフィールドをマップするためにカスタムを使用するためjava.util.Date、DBではHibernateによってUTCとして扱われます。JPAアノテーションを使用しているため、次の依存関係を使用します。

<dependency>
    <groupId>com.montrosesoftware</groupId>
    <artifactId>DbAssist-5.2.2</artifactId>
    <version>1.0-RELEASE</version>
</dependency>

修正の適用は簡単です。たとえば、Spring Bootを使用する場合は@EnableAutoConfiguration、アプリケーションクラスの前にアノテーションがあることを確認する必要があります。別のHibernateバージョンを使用している場合は、github wikiを参照して、修正の適切なバージョンとインストールガイドを見つけてください。この記事でタイムゾーンシフトの問題について詳しく読むこともできます。

于 2016-11-08T13:09:27.230 に答える
0

Joda Time Contribのこの動作は、私のプロジェクトUsertype forJodaTimeおよびJSR310で修正されています。http://usertype.sourceforge.net/を参照してください。これは、実際にはJodaTimeHibernateの代わりになります。

私はこの問題について書きました:http://blog.jadira.co.uk/blog/2010/5/1/javasqldate-types-and-the-offsetting-problem.html

お役に立てれば、

クリス

于 2011-04-16T20:58:41.030 に答える