web-dev-qa-db-ja.com

Java 8 hibernateのLocalDateがTIMESTAMPに誤ってマッピングされる

私はスプリングブート1.4.2を使用します。これは休止状態5.0.11(JPA 2.1)をもたらします。エンティティでJava 8時間クラスを使用したいので、hibernate-Java8を含めます。

私のエンティティはLocalDateフィールドを定義しています。

@Entity
@Table(name = "my_alarms_timeline", indexes = {...})
public class MyAlarm {
    ...
    @Column(name = "validity_date")
    @NotNull
    private LocalDate validityDate;
}

これはH2データベースのDATEにマップされると思います。

私のDBでは、これをvalidity_date DATE NOT NULL,として宣言します。

テストを実行しようとすると、次のエラーが発生します。

[INFO] Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: 
    Schema-validation: wrong column type encountered in column [validity_date] in table [my_alarms_timeline]; 
    found [date (Types#DATE)], but expecting [timestamp (Types#TIMESTAMP)]

驚いたことに、DB定義をvalidity_date TIMESTAMP NOT NULL,に変更すると、エラーが発生します

Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: 
    Schema-validation: wrong column type encountered in column [validity_date] in table [my_alarms_timeline]; 
    found [timestamp (Types#TIMESTAMP)], but expecting [date (Types#DATE)]

これは前のメッセージの逆のメッセージです。

hibernate-Java8を含める代わりに、AttributeConverter<LocalDate, Java.sql.Date>を使用することも試みましたが、同じエラー結果が生成されます。

LocalDateがDBのDATEに正しくマップされるようにするには、どうすればよいですか?

LocalDateTimeフィールドをTIMESTAMPにマップして試したところ、問題なく動作しました...

8
Philipp

そのため、columnDefinition="DATE"アノテーションに@Columnを追加して実行しました。

@Entity
@Table(name = "my_alarms_timeline", indexes = {...})
public class MyAlarm {
    ...
    @Column(name = "validity_date", columnDefinition = "DATE")
    @NotNull
    private LocalDate validityDate;
}

なぜ他の誰もこの問題を見ていません...

12
Philipp

私はこれをSpringでは使用していませんが、「標準」JPAでは次のようなことをしています。

@Converter(autoApply = true)
public class OffsetDateTimeAttributeConverter implements AttributeConverter<OffsetDateTime, Timestamp> {
    @Override
    public Timestamp convertToDatabaseColumn(OffsetDateTime entityValue) {
        if( entityValue == null )
            return null;

        return Timestamp.from(Instant.from(entityValue));
    }

    @Override
    public OffsetDateTime convertToEntityAttribute(Timestamp databaseValue) {
        if( databaseValue == null )
            return null;

        return OffsetDateTime.parse(databaseValue.toInstant().toString());
    }
}

テーブルに「タイムスタンプとタイムゾーン」列があります。次に、@ EntityはOffsetDateTimeを使用します。あなたはこのようなものであなたのデータ型の間で変換することができるはずです。

4
stdunbar

プロジェクトのどこかに次のコードがあると思います。

@EntityScan(basePackageClasses = { Application.class, Jsr310JpaConverters.class })

Hibernate 5.xを使用している場合は、Jsr310JpaConverters.classへの参照を削除する必要があります。そうしないと、HibernateとSpringの両方がJava 8 Date and Timeオブジェクトを処理しようとします。これにより、動作が非常に不安定になる場合があります。 (UTCを使用しないマシンで実行すると、LocalDateインスタンスが誤った値で永続化されるなど)。

また、次のものもすべて削除する必要があります。

@Column(columnDefinition = "DATE")

必要な場合は、休止状態の構成に重大な問題があることを示しています。