web-dev-qa-db-ja.com

JPA 2エンティティでpostgresqlの「タイムスタンプ付きタイムスタンプ」をマッピングする方法

Postgresql(9.0-801.jdbc3 JDBCドライバーを使用)を使用するJPA 2アプリケーション(JPA実装としてHibernate 3.6を使用)があります。

「タイムスタンプ付きタイムスタンプ」フィールドをJPAエンティティーにマッピングできません。

次に例を示します。

_CREATE TABLE theme
(
  id serial NOT NULL,
  # Fields that are not material to the question have been edited out
  run_from timestamp with time zone NOT NULL,
  run_to timestamp with time zone NOT NULL,
  CONSTRAINT theme_pkey PRIMARY KEY (id ),
  CONSTRAINT theme_name_key UNIQUE (name )
)
_

私は次のようにマッピングしようとしました:

_@Entity
@Table(schema = "content", name = "theme")
public class Theme extends AbstractBaseEntity {
    private static final long serialVersionUID = 1L;

    @Column(name = "run_from")
    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    private Date runFrom;

    @Column(name = "run_to")
    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    private Date runTo;

    /* The rest of the entity has been edited out */
_

次の根本的な原因で例外が発生し続けます:_Caused by: org.hibernate.HibernateException: Wrong column type in public.backend_themetopic for column created. Found: timestamptz, expected: date_

私が試したこと

  • _Java.util.Calendar_を_Java.util.Date_で置き換える-違いはありません
  • _Java.sql.Timestamp_の使用-_@Temporal_アノテーションをTimestampに適用できないと不満を述べた
  • _org.joda.time.DateTime_とカスタム_@Type_アノテーション(@Type(type="org.joda.time.contrib.hibernate.PersistentDateTimeTZ"))の併用も機能しませんでした

制約

  • このアプリケーションは「レガシーシステム」と相互作用します-したがって、日付フィールドのタイプを変更することは良いオプションではありません

私の質問は、これらのタイムゾーン対応のタイムスタンプをJPAエンティティにどのようにマッピングすればよいですか?

29
Ngure Nyaga

私は結局、スキーマ検証をオフにすることによって、ハッキーな方法で、この「作業」を行いました。

以前は、<property name="hibernate.hbm2ddl.auto" value="validate"/>"hibernate.hbm2ddl.auto"私のpersistence.xmlで。このプロパティをコメントアウトすると、アプリサーバーが起動し、モデルが「機能しました」。

私の実体の最終的な形は:

@Entity
@Table(schema = "content", name = "theme")
public class Theme extends AbstractBaseEntity {
    private static final long serialVersionUID = 1L;

    @Column(name = "run_from", columnDefinition = "timestamp with time zone not null")
    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    private Date runFrom;

    @Column(name = "run_to", columnDefinition = "timestampt with time zone not null")
    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    private Date runTo;

    /* Getters, setters, .hashCode(), .equals() etc omitted */

これについてかなり読んだ後、私はPostgresqlのタイムスタンプをタイムゾーン列にマップする簡単な方法がないという印象を受けました。

一部のJPA実装+データベースの組み合わせはこれをネイティブにサポートします(EclipseLink + Oracleはその一例です)。 hidanateの場合、jodatime拡張により、通常のタイムスタンプ+タイムゾーンのvarcharフィールドを使用してタイムゾーン対応のタイムスタンプを保存できます(データベーススキーマの変更が制限されていたため、実行できませんでした)。 Jadiraユーザータイプ または完全にカスタムのユーザータイプを使用して、この問題に対処することもできます。

このエンティティの使用例は「読み取り専用」であることに注意する必要があります。そのため、一見単純な「解決策」で済む可能性があります。

9
Ngure Nyaga

追加@Column(columnDefinition= "TIMESTAMP WITH TIME ZONE")

@Column(name = "run_from", columnDefinition= "TIMESTAMP WITH TIME ZONE")
@NotNull
@Temporal(TemporalType.TIMESTAMP)
private Date runFrom;
7
Alexei Osipov