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: See this article for 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.

Advertisements
This entry was posted in java and tagged , , . Bookmark the permalink.

9 Responses to Generating DDL Scripts with Maven

  1. Oleksandr says:

    Good article.
    One question.

    Can hibernate3:hbm2ddl from hibernate3-maven-plugin does the same as ant for you here? Ant invocation is considered to slow down maven execution time.

  2. mafr says:

    Unfortunately, I never got that plugin working, so I chose ant. If you know a way I’d appreciate to hear how you did it. Thanks!

  3. mafr says:

    Thanks a lot! I’ll try it as soon as my holidays are over and I’m back at work.

    Cheers,
    Matthias

  4. mattlf says:

    Did you get it to work with maven2 only? Because lystochok’s post doesn’t seem to exist anymore. Thank you!

  5. mafr says:

    Yes, I finally got it working. Please see my latest article for the solution.

  6. Pingback: So Much for 2010 « Unmaintainable

  7. asa says:

    Nice article.

    However, why not simply let the database be created in the dev environment first by Hibernate, export as SQL and tweak as desired?

    • mafr says:

      That works, too. However, there’s no standard mechanism to extract the schema from a database. The solution presented here works for all database systems and it can run as part of your build process without needing access to a database instance.

Comments are closed.