如何在 JPA 2 实体中映射 postgresql "timestamp with time zone"



我有一个JPA2应用程序(使用Hibernate 3.6作为JPA实现),它使用Postgresql(使用9.0-801.jdbc3 JDBC驱动程序)。

我在将"带时区的时间戳"字段映射到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.Date替换java.util.Calendar-没有差异
  • 使用java.sql.Timestamp-抱怨我无法将@Temporal注释应用于Timestamp
  • org.joda.time.DateTime与自定义@Type注释(@Type(type="org.joda.time.contrib.hibernate.PersistentDateTimeTZ"))一起使用也不起作用

限制

  • 此应用程序与"遗留系统"交互-因此,更改日期字段的类型不是一个好的选择

我的问题是:我应该如何将这些时区感知的时间戳映射到我的JPA实体中?

我最终做出了这个"工作"-以一种很粗糙的方式——通过关闭模式验证。

以前,我在persistence.xml中有<property name="hibernate.hbm2ddl.auto" value="validate"/>"hibernate.hbm2ddl.auto";工作";。

我的实体的最终形式是:

@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 = "timestamp with time zone not null")
@NotNull
@Temporal(TemporalType.TIMESTAMP)
private Date runTo;

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

在阅读了很多关于这方面的内容后,我得到的印象是,没有简单的方法可以将Postgresql时间戳与时区列进行映射。

一些JPA实现+数据库组合本机支持这一点(EclipseLink+Oracle就是一个例子)。对于hibernate,使用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;

最新更新