Generating DDL Scripts with Maven

Java's persistence API (JPA) makes object-relational mapping very convenient. Using Hibernate, tables and sequences are generated automatically which speeds up development significantly. However, in production systems automatic schema creation isn't desired. In many cases you would want to tune the schema a bit, like adding an index for speeding up common access paths, renaming constraints and the like. Additionally, an application should run with as little DB privileges as possible, so it is possible that CREATE TABLE is simply not permitted.

[UPDATE: Seethis articlefor a pure maven solution.]

The usual approach is to create a DDL script containing the required CREATE commands and execute it on the database before deploying the application. Unfortunately, this is a large task if you have many entities and with foreign key constraints, the order of commands matters. So it would be nice if we could generate a working DDL script from our JPA annotations that can be adjusted manually.

Using Hibernate and the hibernatetool Ant task, this is possible. In the following example, I'll show how to configure a Maven project which used the antrun plugin to execute hibernatetool from within Maven.

First of all, we have to attach the antrun plugin to Maven's lifecycle. Add the following to your pom.xml:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-antrun-plugin</artifactId>
      <executions>
        <execution>
          <id>process-classes</id>
          <phase>process-classes</phase>
          <configuration>
            <tasks>
              <ant antfile="src/main/ant/build.xml" inheritRefs="true">
                <target name="schemaexport"/>
              </ant>
            </tasks>
          </configuration>
          <goals>
            <goal>run</goal>
          </goals>
        </execution>
      </executions>
      <dependencies>
        <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-tools</artifactId>
          <version>3.2.0.beta9a</version>
        </dependency>
        <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-entitymanager</artifactId>
          <version>3.2.1.ga</version>
        </dependency>
        <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.14</version>
        </dependency>
      </dependencies>
    </plugin>
  </plugins>
</build>

The plugin configuration references an external build.xml file which contains the hibernatetool invocations. Create a directory src/main/ant and add the following build.xml file:

<?xml version="1.0" encoding="UTF-8"?>

<project>

    <!--
          Generate DDL files for schema creation.
    -->
    <target name="schemaexport">

        <taskdef name="hibernatetool"
                 classname="org.hibernate.tool.ant.HibernateToolTask"/>

        <hibernatetool destdir="target">

            <classpath refid="maven.compile.classpath"/>

            <!-- Use JPA annotations, as opposed to Hibernate's hbm
                 files. If there are multiple persistence units, specify
                 the correct one using the  "persistenceunit" attribute.
            -->
            <jpaconfiguration />

            <!-- Write all CREATE statements to a file. -->
            <hbm2ddl drop="false" create="true" export="false"
                     outputfilename="schema-create.ddl"
                     delimiter=";" format="true"/>

            <!-- Write all DROP statements to a different file. -->
            <hbm2ddl drop="true" create="false" export="false"
                     outputfilename="schema-drop.ddl"
                     delimiter=";" format="true"/>

        </hibernatetool>

    </target>

</project>

Now you can run mvn generate-classes and you will find two DDL files in the target directory: One for creating and one for dropping all tables.

social