5

定義を使用して、Oracle 11g データベースのテーブルにデータを追加しようとしています。

CREATE TABLE FOO_TIME_TEST  
(ID      NUMBER(20) NOT NULL, TIME    TIMESTAMP(6),
 CONSTRAINT FOO_TIME_TEST_PK   PRIMARY KEY (ID) USING INDEX);

CREATE UNIQUE INDEX "foo_time_test_idx" ON "FOO_TIME_TEST" (TIME)

以下の Joda 時間を使用した Hibernate/JPA マッピング

@Type(type = "com.foo.PersistentDateTime")
@Column(name = "TIME")
public DateTime getTime() {
    return time;
}

マッピング クラスの PersistentDateTime 関連ビット

public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws SQLException {
    if (value == null) {
        Hibernate.TIMESTAMP.nullSafeSet(preparedStatement, null, index);
    } else {
        Hibernate.TIMESTAMP.nullSafeSet(preparedStatement, ((DateTime) value).toDate(), index);
    }
}

public int[] sqlTypes() {
    return new int[] { Types.TIMESTAMP, };
}

そして書くコードはこんな感じで、plusTime()を使ってループしていましたが、この2つの呼び出しに分離しました。

{
    DateTime time = new DateTime(2012, 10, 28, 0, 0, DateTimeZone.UTC);
    FooTest data = new FooTest();
    data.setTime(time);
    em.persist(data);
    System.out.println(time + " " + time.getMillis() / 1000 / 60 / 60);
}

{
    DateTime time = new DateTime(2012, 10, 28, 1, 0, DateTimeZone.UTC);
    FooTest data = new FooTest();
    data.setTime(time);
    em.persist(data);
    System.out.println(time + " " + time.getMillis() / 1000 / 60 / 60);
}

出力

2012-10-28T00:00:00.000Z 375384
2012-10-28T01:00:00.000Z 375385

19:23:42,081  WARN JDBCExceptionReporter:100 - SQL Error: 1, SQLState: 23000
19:23:42,081 ERROR JDBCExceptionReporter:101 - ORA-00001: unique constraint (Foo.foo_time_test_idx) violated

一意のインデックスを削除しようとしましたが、コードは成功しますが、データベース内の 2 つの行は同じになります。

ID  Time
1   28-OCT-12 01.00.00.000000000 AM
2   28-OCT-12 01.00.00.000000000 AM

休止状態のトレースを有効にすると、2 つの異なる日付が同じ値にフラット化されているように見えます。

Hibernate: insert into FOO_TIME_TEST (ID, TIME) values (?, ?)
07:38:54,217 TRACE TimestampType:151 - binding '2012-10-28 01:00:00' to parameter: 22
Hibernate: insert into FOO_TIME_TEST (ID, TIME) values (?, ?)
07:38:54,217 TRACE TimestampType:151 - binding '2012-10-28 01:00:00' to parameter: 22

さらにデバッグするには、ojdbc-6.jar のソースが本当に必要です...

11.2.0.2.0 用の ojdbc6_g.jar をダウンロードし、ここで提案されているように -Doracle.jdbc.Trace=true オプションとカスタム Java util log.propertiesとともにクラスパスを配置することで、より多くのデバッグを有効にしました。

これにより、各バインド呼び出しの後に追加情報が提供されます。どちらの場合も 01:00 値が表示されます。

Nov 2, 2012 8:20:21 AM oracle.jdbc.driver.OraclePreparedStatementWrapper setTimestamp
TRACE_30: 3C322E7D Enter: 22, 2012-10-28 01:00:00.0
Nov 2, 2012 8:20:21 AM oracle.jdbc.driver.OraclePreparedStatement setTimestamp
FINE: 3C322E7D Public Enter: 22, 2012-10-28 01:00:00.0
Nov 2, 2012 8:20:21 AM oracle.jdbc.driver.OraclePreparedStatement setTimestampInternal
FINER: 3C322E7D Enter: 22, 2012-10-28 01:00:00.0
4

1 に答える 1

0

タイムゾーンで時間を保存しているので、タイプ TIMESTAMP(3) WITH TIME ZONE を使用することをお勧めします。

CREATE TABLE TIME_TABLE
(
  YOUR_TIME TIMESTAMP(3) WITH TIME ZONE,
  TIME_ZONE  VARCHAR (64 BYTE),
)

hibernate マッピングには Joda クラス org.joda.time.contrib.hibernate.PersistentDateTimeTZ を使用します。以下は XML マッピング スニペットです。

<property name="yourTime" type="org.joda.time.contrib.hibernate.PersistentDateTimeTZ">
    <column name="YOUR_TIME" />
    <column name="TIME_ZONE" />
</property>

私は注釈ベースの Hibernate マッピングに精通していませんが、次のようになると思います (試したことはありません)。

@Type(type = "org.joda.time.contrib.hibernate.PersistentDateTimeTZ")
@Columns(columns = { @Column(name = "YOUR_TIME"), @Column(name = "TIME_ZONE") })
public DateTime getYourTime() {
        return yourTime;
}

これが役立つことを願っています。

PS 使用している Joda DateTime コンストラクターを認識できません。秒とミリ秒の引数がないようです。

于 2013-04-01T09:58:44.390 に答える