Search code examples
mavenddlhibernate-4.xjpa-2.1hibernate3-maven-plugin

Generate DDL script at MAVEN build with Hibernate4 / JPA 2.1


It seems like the hibernate3-maven-plugin used to generate DDL create/drop scripts is not compatible any more with Hibernate 4.3 and newer versions (using JPA 2.1).

I use this plugin configuration :

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>hibernate3-maven-plugin</artifactId>
                <version>3.0</version>
                <executions>
                    <execution>
                        <id>generate-sql-schema</id>
                        <phase>process-sources</phase>
                        <goals>
                            <goal>hbm2ddl</goal>
                        </goals>
                        <configuration>
                            <hibernatetool>
                                <jpaconfiguration persistenceunit="${persistenceUnitName}" />
                                <hbm2ddl update="true" create="true" export="false"
                                    outputfilename="src/main/sql/schema.sql" format="true"
                                    console="true" />
                            </hibernatetool>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

But I get the following error :

[ERROR] Failed to execute goal org.codehaus.mojo:hibernate3-maven-plugin:3.0:hbm2ddl (generate-sql-schema) on project my-project: There was an error creating the AntRun task.
An Ant BuildException has occured: java.lang.NoClassDefFoundError: org/hibernate/util/ReflectHelper: org.hibernate.util.ReflectHelper -> [Help 1]

This class as migrated to a new package : org.hibernate.internal.util.ReflectHelper

However i found no clear way to keep generating DDL create scripts at MAVEN build.

There is no hibernate4-maven-plugin, or any other official way to do it.

So what ? Isn't it a main feature that should be supported ? How to do it ?


Solution

  • As Hibernate 4.3+ now implements JPA 2.1 the appropriate way to generate DDL scripts is to use following set of JPA 2.1 properties :

    <property name="javax.persistence.schema-generation.scripts.action" value="create"/>
    <property name="javax.persistence.schema-generation.create-source" value="metadata"/>
    <property name="javax.persistence.schema-generation.scripts.create-target" value="target/jpa/sql/create-schema.sql"/>
    

    A nice summary of others properties and context of schema generation in JPA 2.1 can be found here : https://blogs.oracle.com/arungupta/entry/jpa_2_1_schema_generation

    And official JPA 2.1 specifications here : https://jcp.org/aboutJava/communityprocess/final/jsr338/index.html

    As this will be generated at runtime, you may want to execute this DDL generation at build.

    Here is the JPA 2.1 approach to generate this script programmatically :

    import java.io.IOException;
    import java.util.Properties;
    
    import javax.persistence.Persistence;
    
    import org.hibernate.jpa.AvailableSettings;
    
    public class JpaSchemaExport {
    
        public static void main(String[] args) throws IOException {
            execute(args[0], args[1]);
            System.exit(0);
        }
    
        public static void execute(String persistenceUnitName, String destination) {
            System.out.println("Generating DDL create script to : " + destination);
    
            final Properties persistenceProperties = new Properties();
    
            // XXX force persistence properties : remove database target
            persistenceProperties.setProperty(org.hibernate.cfg.AvailableSettings.HBM2DDL_AUTO, "");
            persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_DATABASE_ACTION, "none");
    
            // XXX force persistence properties : define create script target from metadata to destination
            // persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_CREATE_SCHEMAS, "true");
            persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_SCRIPTS_ACTION, "create");
            persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_CREATE_SOURCE, "metadata");
            persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_SCRIPTS_CREATE_TARGET, destination);
    
            Persistence.generateSchema(persistenceUnitName, persistenceProperties);
        }
    
    }
    

    As you can see it's very simple !

    Now you can use this in an AntTask, or MAVEN build like this (for MAVEN) :

    <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <version>1.7</version>
        <executions>
            <execution>
                <id>generate-ddl-create</id>
                <phase>process-classes</phase>
                <goals>
                    <goal>run</goal>
                </goals>
                <configuration>
                    <target>
                        <!-- ANT Task definition -->
                        <java classname="com.orange.tools.jpa.JpaSchemaExport"
                            fork="true" failonerror="true">
                            <arg value="${persistenceUnitName}" />
                            <arg value="target/jpa/sql/schema-create.sql" />
                            <!-- reference to the passed-in classpath reference -->
                            <classpath refid="maven.compile.classpath" />
                        </java>
                    </target>
                </configuration>
    
            </execution>
        </executions>
    </plugin>
    

    Note that the official hibernate-maven-plugin also may, or may not, do the trick in some way :

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-maven-plugin</artifactId>
        <version>4.3.1.Final</version>
    </dependency>
    

    Enjoy ! :)