2

この日付は、PostgreSQL9.1データベースのtimestamp without time zone列にあります。

2012-11-17 13:00:00

これはUTCであることが意図されており、UNIXタイムスタンプ(EXTRACT epoch)として選択することで確認しました。

int epoch = 1353157200; // from database
Date date = new Date((long)epoch * 1000);
System.out.println(date.toGMTString()); // output 17 Nov 2012 13:00:00 GMT

ただし、JPA / Hibernateを使用してこの日付を読み取ると、問題が発生します。これは私のマッピングです:

@Column(nullable=true,updatable=true,name="startDate")
@Temporal(TemporalType.TIMESTAMP)
private Date start;

Dateしかし、私が得るのは次のとおりです。

17 Nov 2012 12:00:00 GMT

なぜこれが起こっているのですか、そしてもっと重要なことに、どうすればそれを止めることができますか?

ある時点を普遍的に(java.util.Dateそうするように)保存したいだけであり、明らかにデータを破壊したくないことを除いて、タイムゾーンについてはあまり気にすることができなかったことに注意してください。

ご想像のとおり、データベースに接続するクライアントアプリケーションはUTC + 1(オランダ)にあります。

また、列タイプの選択は、timestamp without time zoneHibernateがスキーマを自動的に生成したときに行われました。timestamp with time zone代わりにそうすべきでしょうか?

4

3 に答える 3

4

データベースがタイムゾーン情報を提供しない場合、JDBCドライバーはそれをJVMのローカルタイムゾーンにあるかのように処理する必要があります(PreparedStatement.setDate(int、Date)を参照)。

アプリケーションを実行している仮想マシンのデフォルトのタイムゾーンを使用して、指定されたパラメーターを指定されたjava.sql.Date値に設定します。

JavadocとJDBC仕様は、etcについて明示的には何も述べていませんResultSetが、一貫性を保つために、ほとんどのドライバーは、データベースから取得した日付にもそのルールを適用します。使用するタイムゾーンを明示的に制御する場合は、適切なタイムゾーンのオブジェクトset/getDate/Time/Timestampも受け入れるさまざまなメソッドを使用する必要があります。Calendar

一部のドライバは、データベースとの間で変換するときに使用するタイムゾーンを指定できる接続プロパティも提供します。

于 2012-11-17T14:44:15.407 に答える
1

列タイプを変更しtimestamp with time zoneて問題を修正したことがわかりました。その場合、他のすべてのタイムスタンプ列もそれに変換する必要があります。

timestamp without time zoneこのことから、HibernateはUTCのように列を読み取るのではなく、ローカルタイムゾーンのように読み取ると結論付けます。UTCとして解釈させる方法がある場合は、お知らせください。

于 2012-11-17T13:32:24.387 に答える
1

問題を解決するためのいくつかの解決策があります:

1)最も簡単な方法は、データベースがこれをサポートしている限り、JDBC接続文字列にタイムゾーンを設定することです。

MySQLの場合useGmtMillisForDatetimes=true、データベースでUTCを強制的に使用するために使用できます。私の知る限り、Postgresはそのようなオプションをサポートしていませんが、Postgresを使用していないので間違っている可能性があります。

2)Javaクライアントプログラムのデフォルトのタイムゾーンを次のように設定します

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

短所:たとえば、プログラムにUIパーツがある場合など、不要なタイムゾーンも変更します。

3)Hibernate専用の特別なゲッターでマッピングを使用します:マッピングファイル内

<property name="myTimeWithTzConversion" type="timestamp" access="property">
  <column name="..." />
</property>

プログラムではget/setMyTimeWithTzConversion()、メンバー変数への休止状態でのみアクセスできますTimestamp myTime。このゲッター/セッターでは、タイムゾーン変換を行います。

3)(これはもう少しプログラミング作業です)を最終的に決定しました。既存のデータベースを変更する必要がなかったため、データベースはUTC + 1(JDBC接続文字列ソリューションを禁止)であり、変更されませんでした。既存のUIに干渉します。

于 2012-11-19T07:52:47.870 に答える