当前位置: 首页 > 面试题库 >

使用Hibernate / JPA和JDK日期进行不需要的自动时区转换

薛宜
2023-03-14
问题内容

我使用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在多个应用程序之间共享。

如何在不将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,

摩西



 类似资料:
  • 问题内容: 我需要将传入日期字符串格式“ 20130212”(YYYYMMDD)转换为12/02/2013(DD / MM / YYYY) 使用。我知道没有这种方法可以做到这一点。谁能帮我? 转换不包含: 问题答案: Java中的ThreadLocal除了编写不可变的类外,还是一种实现线程安全的方法。由于SimpleDateFormat不是线程安全的,因此可以使用ThreadLocal使其成为线程

  • 问题内容: 如何配置JPA /hibernate模式以UTC(GMT)时区在数据库中存储日期/时间?考虑以下带注释的JPA实体: 如果日期为太平洋标准时间(PST)2008-Feb-03 9:30 am,那么我希望数据库中存储2008-Feb-03 5:30 pm的UTC时间。同样,从数据库中检索日期时,我希望将其解释为UTC。因此,在这种情况下530pm是UTC 530pm。显示时,它将被格式化

  • 问题内容: 我有一个返回例如DateTime对象的Web服务:DepartureDate。我使用ajax来获取此代码,并在我看来使用此功能将JSON日期字符串转换为javascript日期对象: 问题是要考虑到客户端计算机上的本地时间,因此不同国家/地区的客户端会获得不同的日期。我想获取从Web服务返回的确切日期。有没有简单的方法可以做到这一点? 问题答案: 问题是考虑了客户端计算机上的本地时间

  • 问题内容: 如何配置JPA /hibernate模式以UTC(GMT)时区在数据库中存储日期/时间?考虑以下带注释的JPA实体: 如果日期是太平洋标准时间(PST)2018-Feb-03 9:30 am,那么我希望数据库中存储2008-Feb-03 5:30 pm的UTC时间。同样,从数据库中检索日期时,我希望将其解释为UTC。因此,在这种情况下,530pm是UTC 530pm。显示时,它将被格式

  • 我在+5:30,即IST时区。 在通过提供year、month和date创建日期期间,节点js将其视为IST并自动扣除-5:30。 节点js通过考虑该日期位于服务器时区,将该日期自动转换为UTC。但在浏览器中,我得到了正确的CST日期没有时间。 2017-03-08T12:28:16.381Z 2017-03-08T17:58:16.000Z 浏览器输出:

  • 问题内容: 我正在使用Spring JPA和Hibernate的项目。可以在Spring applicationContext.xml 文件中指定 persistence.xml中的 大多数内容。 __ 那么是否还需要 persistence.xml ? 谢谢。 问题答案: 更新: Spring 3.1将支持免费的JPA配置,请参阅Spring 3.1 M2:配置增强 。 darioo的答案适合实