How to map oracle timestamp to appropriate java ty

2020-02-14 06:16发布

问题:

I am new to hibernate and I am stumped. In my database I have tables that have a columns of TIMESTAMP(6). I am using Netbeans 6.5.1 and when I generate the hibernate.reveng.xml, hbm.xml files, and pojo files it sets the columns to be of type Serializable. This is not what I expected, nor what I want them to be.

I found this post on the hibernate forums saying to place:

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

in the hibernate.reveng.xml file.

In Netbeans you are not able to generate the mappings from this file (it creates a new one every time) and it does not seem to have the ability to re-generate them from the file either (at least according to this it is slated to be available in version 7).

So I am trying to figure out what to do. I am more inclined to believe I am doing something wrong since I am new to this, and it seems like it would be a common problem for others.

  • So what am I doing wrong?
  • If I am not doing anything wrong, how do I work around this?

I am using Netbeans 6.5, Oracle 10G, and I believe Hibernate 3 (it came with my netbeans).

Edit: Meant to say I found this stackoverflow question, but it is really a different problem.

UPDATE: The oracle jdbc driver I was using (ojdbc14.jar) is 9.0.2.0.0 I have now also tried:

  • ojdbc14.jar version 10.2.0.4.0
  • ojdbc6.jar version 11.2.0.1.0

回答1:

I found a work around for this problem. The issue itself seems to revolve around the fact that Netbeans 6.5 (and I later versions up to this point) do not allow you to reverse engineer a database from an existing hibernate.reveng.xml file. This is slated to be available in version 7.

The work around I found is to create an ant task to recreate the hbm.xml and pojo java files. I currently have this hooked to happen when I do a clean and build, but I am going to try to find a way to to have it completely separate, since it will only need to be ran when the database schema changes.

To accomplish this when you do a clean and build though you need to edit your build.xml file.

The first part is the libraries you will need. So add:

<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>

You should already have the hibernate-tools.jar, hibernate3.jar, and ojdbc14.jar files on you machine. So just change the path to them. The freemaker.jar and jtidy-r938.jar will need to be downloaded, as I did not have those.

Below this in the build.xml you will need to add:

<taskdef name="hibernatetool"
     classname="org.hibernate.tool.ant.HibernateToolTask"
     classpathref="toolslib">
    <classpath>
        <fileset dir="lib">
            <include name="**/*.jar"/>
        </fileset>
    </classpath>
</taskdef>

The last section you will need is the set to run in the post-clean section:

<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>
  • The delete portion will delete the existing hbm and pojo files, before they are re-created.
  • The configurationfile points to your main configuration file.
  • The package name is the dot separated package you want them created in (com.stackoverflow.pojo for example).
  • The revengfile is the reverse engineering xml file to use when creating the hbm and pojo files.
  • The hbm2hbmxml will create the hbm.xml files of your tables.
  • The hbm2java will create the java pojo files of your tables.

Now to get the Oracle Timestamps to be something other than Serializable, edit the hibernate.reveng.xml file and add:

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

just after the schema-selection tag.

So a clean and build and the timestamps will not be java.sql.Timestamp instead of Serializable objects.

This is a long answer I know, but this should also work for any other changes that you would have to set in the hibernate.reveng.xml file (I think). I am no expert in hibernate, so your mileage may vary with this.

UPDATE: So after some googling I found this site about custom ant tasks in Netbeans. So I simply changed the name of the target to be gen-dao and now it does not run every time I do a clean and build, just when I specifically invoke it.



回答2:

I faced similar issue and resolved it by writing my own RevengNamingStrategy.

I have a table having two columns as TIMESTAMP_WITH_TIMEZONE and TIMESTAMP_WITH_LOCAL_TIMEZONE and in reverse engineering process they are mapping to seralizable.

SqlTypes of TIMESTAMP_WITH_TIMEZONE and TIMESTAMP_WITH_LOCAL_TIMEZONE types are -101 and -102.And As there is no hibernate mapping types in java.sql.Types for these types,hence they are mapping to seralizable.

So Wrote my own RevengNamingStrategy,which converts these type to Timestamp.Which intern converts to 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;
    }

}