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エンティティにどのようにマッピングすればよいですか?
私は結局、スキーマ検証をオフにすることによって、ハッキーな方法で、この「作業」を行いました。
以前は、<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ユーザータイプ または完全にカスタムのユーザータイプを使用して、この問題に対処することもできます。
このエンティティの使用例は「読み取り専用」であることに注意する必要があります。そのため、一見単純な「解決策」で済む可能性があります。
追加@Column(columnDefinition= "TIMESTAMP WITH TIME ZONE")
@Column(name = "run_from", columnDefinition= "TIMESTAMP WITH TIME ZONE")
@NotNull
@Temporal(TemporalType.TIMESTAMP)
private Date runFrom;