Monday, February 1, 2016

Hibernate tools reverse engineering using Maven

Hibernate tools allows to generate mapping or Java code through reverse engineering, schema generation through Ant Tasks. There is a Maven plugin hibernate3-maven-plugin but I managed to make it work only with 2.2 version, which comes with an old version of hibernate-tools. Of course, there is the idea of running hibernate tools Ant tasks from Maven. Although Maven beautifuly run Ant tasks, I had quite hard time trying to make it work with the latest stable version of hibernate-tools, mostly because all the examples I found are heavily outdated. The current post describes step by step this process.

The pom.xml

We'll modify pom.xml by creating a Ant task runner to generate JPA entities from a given database. My database is Postgresql, if you are using something else, you'll have to modify the driver in the plugin dependency zone. The only necessary thing in the Maven project's pom is:
 
<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.8</version>
    <executions>
        <execution> <!--mvn antrun:run@hbm2java-->
            <id>hbm2java</id>
            <phase>none</phase>
            <configuration>
                <target>
                    <echo message="Start generating entities .."/>
                    <taskdef name="hibernatetool"
                    classname="org.hibernate.tool.ant.HibernateToolTask"/>
                    <hibernatetool>
                        <jdbcconfiguration
                 revengfile="src/your/path/to/hibernate.reveng.xml"
                            packagename="your.package.name"
                            detectmanytomany="true"
                   configurationfile="src/your/path/to/hibernate.cfg.xml"/>
                <hbm2java destdir="src/main/java" jdk5="true" ejb3="true"/>
                    </hibernatetool>
                    <echo message="End generating entities"/>
                </target>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.11.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.3.11.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.common</groupId>
            <artifactId>hibernate-commons-annotations</artifactId>
            <version>4.0.5.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>1.0.0.Final</version>
        </dependency>
        <dependency>
            <groupId>javax.transaction</groupId>
            <artifactId>jta</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.8</version>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.4.1207.jre7</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-tools</artifactId>
            <version>4.3.2.Final</version>
            <exclusions>
                <exclusion>
                    <groupId>*</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
</plugin>

The reddish zones are the only ones needing configuration. There are 2 important files:

hibernate.cfg.xml

  • It contains the database connection details:

 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</property>
    <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
    <property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/vetcab</property>
    <property name="hibernate.connection.username">postgres</property>
    <property name="hibernate.connection.password">postgres</property>
  </session-factory>
</hibernate-configuration>


Just modify the above file accordingly.

hibernate.reveng.xml

      • It configures the process of reverse engineering. For more details about how this file should look like go on official documentation. Bellow you can see an example:
   
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-reverse-engineering PUBLIC "-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd" >

<hibernate-reverse-engineering>
    <table-filter match-schema="public" match-name="sec_authorities"/>
    <table-filter match-schema="public" match-name="sec_users"/>
    <table-filter match-schema="public" match-name="sec_user_authorities"/>

    <table schema="public" name="sec_users">
        <meta attribute="extra-import">java.util.stream.Collectors</meta>
        <meta attribute="extra-import">java.util.List</meta>
        <meta attribute="extra-import">javax.persistence.Transient</meta>
        <meta attribute="class-code">
        <![CDATA[
    @Transient
    public List<SecAuthority> getSecAuthorities() {
        return getSecUserAuthorities().stream().map(e -> e.getSecAuthority()).collect(Collectors.toList());
    }

        ]]>
        </meta>
        <primary-key>
            <generator class="identity"></generator>
        </primary-key>
    </table>

    <table schema="public" name="sec_authorities">
        <meta attribute="class-description">
            Javadoc for the Person class
            @author eugen
        </meta>
        <primary-key>
            <generator class="identity"></generator>
        </primary-key>
    </table>

    <table schema="public" name="sec_user_authorities">
        <primary-key>
            <generator class="identity"></generator>
        </primary-key>
    </table>

</hibernate-reverse-engineering>

Now you can run it with:
mvn antrun:run@hbm2java
command. If you have modified templates (see the documentation) then, in pom.xml, modify the hibernate tool tag to look like:
<hibernatetool templatepath="src/the/path/to/the/directory/containing/pojo/directory">

The above path must point to the parent of the directory named pojo, containing your templates.   Also, if you have a custom reverse engineering strategy class the, in pom.xml add this attribute to jdbcconfiguration tag.
reversestrategy="fully.qualified.name.CustomDelegatingReverseEngineeringStrategy"

That's all, hope it helped. Don't forget to comment on my post.

1 comment:

  1. It is helpful, possibly change hibernate.reveng.xml like an example for one table + some basic comments. This will increase learning effectivity

    ReplyDelete