【问题标题】:Hibernate + JodaTime mapping different typesHibernate + JodaTime 映射不同类型
【发布时间】:2014-07-22 22:05:59
【问题描述】:

我正在使用休眠逆向工程并试图让我的时间戳映射到 JodaTime 类型。

我已经正确设置了我的 hibernate.reveng.xml 文件

<sql-type jdbc-type="TIMESTAMP" hibernate-type="org.joda.time.contrib.hibernate.PersistentDateTime" not-null="true"></sql-type>

问题是,当我运行 rev-eng 进程时,我的 Java 类也会将成员创建为 PersistentDateTime 对象,但我不希望这样,因为它们不可用。我需要 java 对象是 org.joda.time.DateTime

所以我尝试创建自定义工程策略

public class C3CustomRevEngStrategy extends DelegatingReverseEngineeringStrategy {

public C3CustomRevEngStrategy(ReverseEngineeringStrategy res) {
    super(res);
}

public String columnToHibernateTypeName(TableIdentifier table, String columnName, int sqlType, int length, int precision, int scale, boolean nullable, boolean generatedIdentifier) {
    if(sqlType==Types.TIMESTAMP) {
        return "org.joda.time.DateTime";
    }    else {
        return super.columnToHibernateTypeName(table, columnName, sqlType, length, precision, scale, nullable, generatedIdentifier);
    }
}

}

我的想法是休眠映射文件将获取 hibernate.reveng.xml 文件设置,而 java 对象将从自定义策略文件获取设置...但事实并非如此。映射文件和对象都是“org.joda.time.DateTime”类型,这不是我想要的。

我怎样才能实现我的目标?另外,我没有使用注释。

  • 休眠 3.6
  • JodaTime 2.3
  • JodaTime-Hibernate 1.3

谢谢

编辑:明确问题是什么

在逆向工程之后,这就是我在映射文件和 POJO 类中得到的内容

<property name="timestamp" type="org.joda.time.contrib.hibernate.PersistentDateTime">
private PersistentDateTime timestamp;

作为 POJO 属性,PersistentDateTime 对我来说毫无用处,因为我不能用它做任何事情,例如时间操作或任何事情。所以这就是我在逆向工程后想要的

<property name="timestamp" type="org.joda.time.contrib.hibernate.PersistentDateTime">
private org.joda.time.DateTime timestamp;

使用下面建议的 Jidira 库给我同样的结果,一个我不能使用的 POJO。

【问题讨论】:

  • 如果我的回答不能解决您的问题,请告诉我。它可能只需要一些调整

标签: java hibernate reverse-engineering jodatime hibernate-tools


【解决方案1】:

Hibernate 工具似乎没有将 Hibernate 类型与 Java 类型分开。如果您要使用注解,这会更清楚,因为在这种情况下您需要一个 @Type 注解,而 Hibernate 根本不会生成该注解。因此,在这里使用公开的 API 将无济于事。

幸运的是,Hibernate 允许您插入实际代码(或 XML)生成它进行处理之后。您可以通过替换它用来生成 XML 和 Java 代码的 Freemarker 模板来做到这一点。但是,您需要使用 Ant 进行逆向工程。

要开始为此目的使用 Ant(如果您还没有这样做的话),您可以使用您的依赖管理器将 Hibernate Tools 作为构建时依赖项拉入,或者下载一个 JAR。将 jar 放在 Ant 的类路径中,但也从中提取模板文件:因为您使用的是 XML 配置,所以您会对 /hbm 目录感兴趣。然后使用&lt;taskdef&gt; 添加任务,并假设您将模板提取到TPL_PATH/hbm/*.ftl,使用&lt;hibernatetool templatepath="TPL_PATH" ...&gt; 调用它。 (有关更多信息,请参阅下面的文档链接)。使用 Ant 还有助于自动化,例如在没有 Eclipse 的 CI 服务器上。

您需要将hibernate-type="org.joda.time.DateTime" 保留在hibernate.reveng.xml 中,以便正确生成Java 文件,但在生成的XML 中将其替换为org.joda.time.contrib.hibernate.PersistentDateTime。为此,请编辑TPL_PATH/hbm/property.hbm.ftl,将${property.value.typeName} 替换为${javaType},并在使用之前将javaType 分配给正确的值:

<#assign javaType=property.value.typeName>
<#if javaType.equals("DateTime")>
<#assign javaType="org.jadira.usertype.dateandtime.joda.PersistentDateTime">
</#if>
<property
    name="${property.name}"
    type="${javaType}"
...

您可能希望删除换行符以保持生成的 XML 干净。

这在 http://docs.jboss.org/tools/archive/3.2.1.GA/en/hibernatetools/html/codegen.html#d0e6349 的 Hibernate 工具文档中都有描述 - 除了文档没有确切告诉您需要修改哪些模板,您需要通过阅读模板来弄清楚。

【讨论】:

    【解决方案2】:

    JodaTime-Hibernate 库已弃用,这可能是您的问题的根源。但是不要失望,因为有(更好的)替代方案。

    您将需要使用 JadiraTypes 库从 Hibernate 创建正确的 JodaTime 对象。将库which can be found here 添加到您的项目类路径中,然后将您的类型更改为org.jadira.usertype.dateandtime.joda.PersistantDateTime。所有 JodaTime 对象在该包中都有相应的映射,因此如果您决定更改为另一个对象,则只需更新您的类型。

    这应该确保您的对象被正确创建。

    我应该在我的答案中添加一个警告,即我从未将 JadiraTypes 库与 Hibernate 3 一起使用。如果它只支持 Hibernate 4(我不明白为什么会这样,但是......)让我知道我会删除我的答案。

    【讨论】:

    • 不幸的是,我仍然在第 1 方。我有同样的问题,在逆向工程之后,我的映射文件类型和 POJO 类型是相同的。我需要我的映射文件为 PersistentDateTime 类型,我的 POJO 类型为 DateTime。拥有 POJO PersistentDateTime 对编程毫无用处,因为您无能为力。不能对它进行任何日期操作或任何操作。也许我并不完全清楚我想要什么,所以我会用一个例子来更新我的帖子底部。我很感谢你的帮助
    • 逆向工程完成后,是否有什么阻止您更新实际 POJO 中的实例?
    • 目前这就是我正在做的事情,但我正在寻找方便。特别是由于该项目仍处于起步阶段,因此需求更改和数据库更新非常频繁。因此,如果有办法将其构建到 rev-eng 流程中,我希望找出如何让生活更轻松。
    • 在我看来,像我在 OP 中所做的那样扩展 DelegatingReverseEngineeringStrategy 类是可行的方法。不知何故,将生成 POJO 和映射文件的进程分开,这样我就可以做一些自定义声明,我现在才确定如何做到这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 2010-09-25
    • 2011-03-11
    相关资源
    最近更新 更多