使用Hibernate / JPA和JDK日期进行不需要的自动时区转换
我使用Hibernate(4.2)作为持久性提供程序,并且我有一个包含Date字段的JPA实体:
@Entity@Table(name = "MY_TABLE")
public class MyTable implements Serializable {
. . .
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "START_DATE")
private Date startDate;
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
. . .
}
对应于START_DATE的列定义为START_DATE TIMESTAMP
(无时区)。
我在应用程序内部使用Joda-
Time(2.3)处理日期(始终使用UTC),并且在持久化Entity之前,我使用toDate()
Joda的DateTime
类方法获取JDK
Date
对象以遵守映射。 :
public void myMethod(DateTime startDateUTC) { . . .
MyTable table = /* obtain somehow */
table.setStartDate(startDateUTC.toDate());
. . .
}
当我在数据库中查看存储的值时,我注意到某个地方(JDK?Hibernate?)使用运行代码的JVM的默认时区来转换Date值。在我的情况下是“美国/芝加哥”。
该问题确实在夏令时(DST)附近显现出来。例如,如果内部时间是
2014-03-09T02:55:00Z
它存储为
09-Mar-14 03:55:00
我想要的是将其存储为
09-Mar-14 02:55:00
但是,在CDT中,不存在3月9日凌晨2:55(“spring向前”)。因此(JDK?Hibernate?)正在将日期向前滚动。
我希望立即将存储在数据库中的内容保存在UTC中。毕竟,这就是我在应用程序内部处理它的方式,但是一旦我将其保留下来,它就会立即转换为我的默认时区。
注意:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
如何在不将JVM默认时区设置为UTC的情况下在UTC中存储日期?
回答:
我自己遇到了这个。我看到的是,即使您已在日期中将UTC指定为时区(并且可以通过打印出来并在末尾看到“
Z”来查看),但出于某种原因,JVM还是想接管并使用JVM的默认时区为您转换日期。
无论如何,您需要一个自定义映射来解决此问题。尝试使用 Jadira:
@Entity@Table(name = "MY_TABLE")
public class MyTable implements Serializable {
. . .
@Column(name = "START_DATE")
@Type(type="org.jadira.usertype.dateandtime.legacyjdk.PersistentDate")
private Date startDate;
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
. . .
}
默认情况下,Jadira的PersistentDate
类在将日期转换为要存储在数据库中的毫秒值时,使用UTC作为时区。您可以指定其他时区,但听起来像是要存储UTC。
就像您的帖子中的注释所暗示的那样,有时您用来查询数据库的工具正在为您进行愚蠢的自动(基于我的JDK默认TZ的转换),使您相信该值仍然不正确。
您也可以尝试存储原始值(作为INTEGER),只是为了使自己确信已存储了正确的毫秒值。
HTH,
摩西
以上是 使用Hibernate / JPA和JDK日期进行不需要的自动时区转换 的全部内容, 来源链接: utcz.com/qa/421393.html