如何在Hibernate中将Oracle时间戳映射到适当的Java类型?

4
我是新手,对Hibernate感到困惑。在我的数据库中,有一些表格的列类型是TIMESTAMP(6)。我正在使用Netbeans 6.5.1,当我生成hibernate.reveng.xmlhbm.xml文件pojo文件时,它将这些列设置为Serializable类型。这不是我预期的,也不是我想要的。
我在Hibernate论坛上找到了这篇帖子,说要添加以下内容:
<sql-type jdbc-type="OTHER" hibernate-type="java.sql.Timestamp" />

需要编辑 hibernate.reveng.xml 文件。

在Netbeans中,您无法从此文件生成映射(每次都会创建一个新的),并且似乎也没有重新生成它们的能力(至少根据 这篇文章,这将在7.x版本中提供)。

因此,我正在努力弄清楚该怎么做。考虑到其他人可能也会遇到这个常见问题,我倾向于认为是我做错了什么。

  • 那我做错了什么?
  • 如果我没有做错什么,我该如何解决这个问题?

我使用Netbeans 6.5,Oracle 10G和Hibernate 3(它随Netbeans一起提供)。

编辑: 我想说我发现了这个 stackoverflow 问题,但实际上是一个不同的问题。

更新: 我使用的Oracle JDBC驱动程序是ojdbc14.jar,版本为9.0.2.0.0。 现在我还尝试过:

  • ojdbc14.jar版本10.2.0.4.0
  • ojdbc6.jar版本11.2.0.1.0

你使用的JDBC驱动程序确切版本是什么? - Pascal Thivent
抱歉,我从未直接使用过Hibernate。但是,如果通过JPA使用Hibernate,则需要使用@Temporal注释。 - vickirk
@vickirk 这个问题是关于逆向工程的... - Pascal Thivent
@Pascal Oracle JDBC驱动程序是ojdbc14.jar。这就是你所说的版本吗? - Jacob Schoen
不会的话,你可以在 ojdbc14.jar 的 META-INF/MANIFEST.MF 文件中找到版本信息。 - Pascal Thivent
@Pascal Thivent:抱歉,你是正确的,我在错误的问题上添加了我的评论 :-( - vickirk
2个回答

2

我遇到了类似的问题,并通过编写自己的 RevengNamingStrategy 解决了它。

我有一个表,其中包含两个列分别为 TIMESTAMP_WITH_TIMEZONE 和 TIMESTAMP_WITH_LOCAL_TIMEZONE,在反向工程过程中它们映射到 seralizable。

TIMESTAMP_WITH_TIMEZONE 和 TIMESTAMP_WITH_LOCAL_TIMEZONE 类型的 SqlTypes 分别为 -101 和 -102。由于在 java.sql.Types 中没有针对这些类型的 hibernate 映射类型,因此它们被映射到 seralizable。

所以我编写了自己的 RevengNamingStrategy,将这些类型转换为 Timestamp,然后转换为 hibernate TimeStampType。

public class OracleRevengNamingStrategy extends DefaultRevengNamingStrategy {

    private static final Integer TIMESTAMP_WITH_TIMEZONE_SQL_CODE = -101;

    private static final Integer TIMESTAMP_WITH_LOCAL_TIMEZONE_SQL_CODE = -102;


    public OracleRevengNamingStrategy(ReverseEngineeringStrategy delegate) {
        super(delegate);
    }

    // Converts Timestamp with tomezone and Time stamp with local time zone to Timestamp
    @Override
    public String columnToHibernateTypeName(TableIdentifier table, String columnName, int sqlType, int length, int precision, int scale,
                                            boolean nullable, boolean generatedIdentifier) {
        String type;

        if (sqlType == TIMESTAMP_WITH_TIMEZONE_SQL_CODE || sqlType == TIMESTAMP_WITH_LOCAL_TIMEZONE_SQL_CODE) {
            type = "timestamp";
        } else {
            type = super.columnToHibernateTypeName(table, columnName, sqlType, length, precision, scale, nullable, generatedIdentifier);
        }

        return type;
    }

}

2
我找到了一个解决方法。问题本身似乎围绕着Netbeans 6.5(以及此后的版本)不允许您从现有的hibernate.reveng.xml文件中反向工程化数据库。这将在7版中提供。
我发现的解决方法是创建一个ant任务来重新创建hbm.xml和pojo java文件。我目前已经将其挂钩在清理和构建时发生,但我将尝试找到一种完全分离的方式,因为它只需要在数据库架构更改时运行。
要完成此操作,请编辑build.xml文件。
第一部分是您需要的库。所以添加:
<path id="toolslib">
        <path location="lib/hibernate-support/hibernate-tools.jar" />
        <path location="lib/hibernate-support/hibernate3.jar" />
        <path location="lib/hibernate-support/freemarker.jar" />
        <path location="lib/hibernate-support/jtidy-r938.jar" />
        <path location="lib/ojdbc14.jar" />
</path>

你应该已经在你的机器上拥有hibernate-tools.jar、hibernate3.jar和ojdbc14.jar文件。只需更改路径即可。需要下载freemaker.jarjtidy-r938.jar,因为我没有这些文件。
build.xml中,在下面添加:
<taskdef name="hibernatetool"
     classname="org.hibernate.tool.ant.HibernateToolTask"
     classpathref="toolslib">
    <classpath>
        <fileset dir="lib">
            <include name="**/*.jar"/>
        </fileset>
    </classpath>
</taskdef>

您需要的最后一部分是在post-clean部分运行的设置:

<target name="-post-clean">
        <delete dir="src/*Put the foler where your pojos and hbm.xml files are located*"/>
        <hibernatetool>
            <jdbcconfiguration
                configurationfile="src\hibernate.cfg.xml"
                packagename="*the package where you want them recreated*"
                revengfile="src\hibernate.reveng.xml"
                detectmanytomany="true"
            />
            <hbm2hbmxml destdir="src" />
            <hbm2java  destdir="src" />
        </hibernatetool>
</target>
  • 删除部分将删除现有的hbm和pojo文件,然后重新创建。
  • configurationfile指向您的主配置文件。
  • 包名称是您想要创建的点分隔包(例如com.stackoverflow.pojo)。
  • revengfile是在创建hbm和pojo文件时使用的反向工程xml文件。
  • hbm2hbmxml将创建您的表的文件。
  • hbm2java将创建您的表的java pojo文件。

现在,为了使Oracle Timestamps成为除Serializable以外的其他内容,请编辑hibernate.reveng.xml文件并添加:

<type-mapping>
        <sql-type jdbc-type="OTHER" hibernate-type="java.sql.Timestamp" />
</type-mapping>

在模式选择标签之后进行清理和构建,时间戳将不再是Serializable对象,而是java.sql.Timestamp
我知道这是一个长答案,但我认为这对于您必须在hibernate.reveng.xml文件中设置的任何其他更改也应该起作用(我想)。我不是Hibernate专家,所以您的结果可能会有所不同。
更新:经过一番搜索,我发现了Netbeans中自定义ant任务的网站。所以我只需将目标的名称更改为gen-dao,现在每次进行清理和构建时它都不会运行,只有当我明确调用它时才会运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接