【问题标题】:hibernate 4 and joda-time休眠 4 和 joda-time
【发布时间】:2012-02-16 23:40:18
【问题描述】:

他们婚姻幸福吗?

我正在使用最新版本的 hibernate (4) 和 joda-time hibernate support 的 1.3 版本,我也相信这是当前的最新版本。

使用注释时,一切似乎都正常(按预期创建日期列):

@Column
@Type(type="org.joda.time.contrib.hibernate.PersistentLocalDate")
private LocalDate myDate; 

将这些版本一起使用是否有任何已知问题?

更新 事实证明,列已创建但无法填充任何数据:

处理程序处理失败;嵌套异常是 java.lang.AbstractMethodError: org.joda.time.contrib.hibernate.PersistentLocalDateTime.nullSafeSet

它们不兼容,我应该使用usertype请参阅下面的答案。

【问题讨论】:

  • 你刚刚告诉我们他们确实合作过,不是吗?
  • @skaffman 除了列创建之外,我没有测试过任何其他东西......据我了解,必须针对较新版本的 hibernate 重新编译以前的版本(joda-time lib)。这敲响了警钟 - 因此问题......
  • 他们的婚姻并不幸福,hibernate 有其他的关系......和 ​​joda.. :/.. 她受伤了
  • 导入 LocalDate 时也要小心,因为它现在在 Java 8 中也可用。

标签: java hibernate jodatime


【解决方案1】:

明显缺乏文档,这意味着写下集成所需的步骤可能对我有所帮助。确保您的库是最新的。

你需要:[假设你已经有 hibernate4]

joda-time最新版本

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.0</version>
</dependency>

和用户类型库

<dependency>
    <groupId>org.jadira.usertype</groupId>
    <artifactId>usertype.core</artifactId>
    <version>3.0.0.CR1</version>
</dependency>

然后在实体类中使用以下内容(不必是 LocalDateTime,可以是任何可用的持久类):

import org.joda.time.LocalDateTime;

对于列定义:

@Column(name="updated", nullable = false)
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime")
private LocalDateTime updated;

【讨论】:

  • 我们如何知道它映射到我们选择的数据库中的什么类型?
  • 对,所以使用自动生成表格并查看输出?
  • 是的,这就是我要做的 - 挖掘休眠文档是一个挑战
  • 如果有人遇到同样的问题:我刚刚遇到了 UserType 的新 auto-registration feature,它注册了一大堆 JodaTime 类型,但 不是 LocalDateTime。如上所述指定类型仍然是您唯一的选择。
  • Stefan,您应该会发现 LocalDateTime 也在最新版本(3.0.0.GA)中注册。
【解决方案2】:

我将把它作为一个单独的答案添加,因为我认为它对于升级到 Hibernate 4 并且需要迁移到使用 jadira 的持久时间类型的任何人来说都是重要信息。这个页面在hibernate 4 和jodatime 的google 搜索结果中排名很高,所以在此添加。 (有关此问题的单独讨论,请参阅:Joda time DateTime incorrectly stores in database

如果您处于 UTC 以外的时区,则需要进行重要的配置才能获得与使用 joda-time hibernate-support 类型相同的行为。 jadira 的时间类型默认工作的方式是,在持久化到数据库之前将所有值转换为 UTC 时区,并在从数据库加载值时转换回系统的时区。

升级后,当我在数据库中有很多带有我的确切时区的时间戳时(UTC+1(夏令时+2)),我被这个烧伤了。在升级到 Hibernate 后加载 4、1 或 2 小时(取决于时间戳是否在夏令时)被添加到数据库中的值中,这意味着所有现有时间戳都被错误地呈现。此外,新的时间戳值使用 UTC 时区存储在数据库中,导致它们在应用程序中正确显示,但在数据库中显示错误。总而言之,时区和时间戳一团糟。

因此,为了获得与 joda-times hibernate-support 相同的行为(被持久化的日期时间是相关服务器的时区,并且数据库中的时间戳与正在加载的时间戳相同应用程序),必须将以下属性添加到 JPA/Hibernate 配置中(在我的情况下,hibernate.properties):

jadira.usertype.autoRegisterUserTypes=true
jadira.usertype.databaseZone=jvm
jadira.usertype.javaZone=jvm

这将确保数据库中的时间戳与应用程序的时区相同,而应用程序的时区又是 jvm 的时区(在大多数情况下是应用程序服务器的时钟)。

此外,据我了解,autoRegisterUserTypes-property 消除了对选择常见类型的 @Type-annotation 的需要,其中包括 Jodatime 类型 DateTimeLocalDate

【讨论】:

  • 既然你已经解决了你的问题,而且和这个问题没有直接关系,我会删除我的cmets并标记你的删除,所以我们保持评论部分的清洁和重点。
  • 只是一个问题:为什么不将每个时间戳存储在 UTC 时间?如果服务器移动到不同的时区怎么办?恕我直言,最好将所有时间戳存储在 UTC 时间,让客户决定他所在的时区。
  • 作为一般规则,我会同意。但就我而言,服务器不可能移动到不同的时区。此外,这里的问题是默认行为发生了变化,在我不知情的情况下。所以当你不知道会发生这种情况时,你无法迁移你的数据,最终得到一组不同时区的时间戳,这当然不好。但是,如果它对您的项目有意义,您可以跳过此处提供的设置,而是迁移您的数据库。使用所有 UTC 的负面影响是 SQL 报告变得棘手或错误。
  • 考虑到这一点,我确实发现将日期存储在服务器使用的另一个时区中存在根本性错误。在 SQLServer 中,日期时间存储为自 1900-01-01 以来的天数,以及自午夜以来的时钟滴答数。将日期转换为不同的时区时,您还更改了日期的内部表示,这实际上使其不准确。不知道这在实践中是否真的是一个问题,但我知道有些程序使用日期的内部表示来计算正确的时区偏移量。
猜你喜欢
  • 2012-06-05
  • 2011-07-03
  • 1970-01-01
  • 2018-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-07
相关资源
最近更新 更多