java - 使用 Hibernate/JPA 和 JDK Date 的不需要的自动时区转换

标签 java hibernate date datetime jpa

我使用 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),并且在持久化实体之前,我使用 toDate() 方法Joda 的 DateTime 类获取 JDK Date 对象以遵守映射:

public void myMethod(DateTime startDateUTC) {
  . . .
  MyTable table = /* obtain somehow */
  table.setStartDate(startDateUTC.toDate());
  . . .
}

当我在数据库中查看存储的值时,我注意到某处(JDK?Hibernate?)使用运行代码的 JVM 的默认时区转换日期值。在我的例子中是“美国/芝加哥”。

问题真正在夏令时 (DST) 附近显现出来。例如,如果内部时间是

2014-03-09T02:55:00Z

它被存储为

09-Mar-14 03:55:00

我想要的是将其存储为

09-Mar-14 02:55:00

但是,在 CDT 中,3 月 9 日凌晨 2:55 不存在(“Spring forward”)。所以某些东西(JDK?Hibernate?)正在将日期向前推进。

我希望存储在数据库中的即时时间为 UTC。毕竟,这就是我在我的应用程序内部处理它的方式,但是一旦我将其移交给持久化,它就会转换为我的默认时区。

注意:我无法使用设置默认时区

TimeZone.setDefault(TimeZone.getTimeZone("UTC"))

因为我运行的 JVM 在多个应用程序之间共享。

如何在不将 JVM 默认时区设置为 UTC 的情况下以 UTC 格式存储日期?

最佳答案

我自己遇到过这个。我看到的是,即使您已将 UTC 指定为 Date 中的时区(并且可以通过打印出来并在末尾看到“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,

摩西

关于java - 使用 Hibernate/JPA 和 JDK Date 的不需要的自动时区转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22210570/

相关文章:

java - Xcode支持Java程序编译和运行吗?

java - 如何通过 "Global default typing"在 Jackson 中启用 "jackson2ObjectMapperBuilder"

java - 显示映射的 2 个表的结果后,我应该在哪里关闭 Hibernate session 对象?

hibernate 多对多配置

JAVASCRIPT 从 datas.date 获取短日后显示全日

java - String replace() 和 replaceAll() 的区别

java - XML 架构位置最佳实践

java - 如何在 Java Spring 和 Hibernate 的单个事务中管理 2 个 DAO 方法?

用于解析日期时间的 C 库

mysql - 将日期时间模式 'y-M-d H:m:s' 选择条件与日期类型进行比较