Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate SchemaExport and Persistence unit

A followup question to my previous question: Generate an SQL DB creation script with Hibernate 4

The goal is to have a command line tool able to generate a file with the SQL schema of a given persistence unit (similarly to the hibernatetool-hbm2ddl Ant task present in the Hibernate Tools).

This, as per the answer to my previous question, can be achieved with org.hibernate.tool.hbm2ddl.SchemaExport.

Instead of adding all the entities to the Configuration (as suggested in the previous answer) I would like to specify a PersistenceUnit.

Is it possible to add a persistence unit to an Hibernate Configuration?

Something like

Properties properties = new Properties();
properties.put( "hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect" );
...
EntityManagerFactory entityManagerFactory =
    Persistence.createEntityManagerFactory( "persistentUnitName", properties );
Configuration configuration = new Configuration();

... missing part ...

SchemaExport schemaExport = new SchemaExport( configuration );
schemaExport.setOutputFile( "schema.sql" );
...

Edit as requested in the comments a sample persistence.xml. Each class is annotated with @Entity

<persistence
    xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
    version="1.0"
>

    <persistence-unit
        name="doiPersistenceUnit"
        transaction-type="JTA"
    >

        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>jdbc/doi</jta-data-source>


        <class>ch.ethz.id.wai.doi.bo.Doi</class>
        [...]
        <class>ch.ethz.id.wai.doi.bo.DoiPool</class>

        <exclude-unlisted-classes>true</exclude-unlisted-classes>

        <properties>
            <property name="hibernate.show_sql"                     value="false" />
            <property name="hibernate.format_sql"                   value="false" />
            <property name="hibernate.connection.characterEncoding" value="utf8" />
            <property name="hibernate.connection.charSet"           value="utf8" />
        </properties>

    </persistence-unit>

</persistence>
like image 351
Matteo Avatar asked Jan 04 '13 16:01

Matteo


1 Answers

Well, if your classes are mapped via xml mappings (hbms) - you can add the documnets or jar files that include the xmls straight to the Configuration instance using config.addJar(myJarFile) and config.add(myXmlFile).

However, if you want your annotated classes to be scanned - I know of no such straightforward option through Hibernate (addPackage adds metadata and not classes).

You may implement your own scan logic and add all annotated classes with config.addAnnotatedClass(myAnnotatedClass) (or perhaps do it per specific packages you know for containing you ORM classes and thus maybe save some time).

UPDATE 2

Oh, even better, you can just iterate the persistence unit's ManagedTypes via getManagedTypes():

EntityManagerFactory entityManagerFactory =
    Persistence.createEntityManagerFactory( unitName, config.getProperties() );
final Set<ManagedType<?>> managedTypes =
    entityManagerFactory.getMetamodel().getManagedTypes();
    for ( ManagedType<?> managedType : managedTypes ) {
    final Class<?> javaType = managedType.getJavaType();
    config.addAnnotatedClass( javaType );
}

UPDATE

You can determine the PersistenceUnit of each Entity - without parsing the xml - by checking against the relevant EntityManagerFactory:

Class aClass = ... // get the class from your scanning
EntityManagerFactory entityManagerFactory =
    Persistence.createEntityManagerFactory( unitName, config.getProperties() );
ManagedType<?> managedType = null;
try {
    managedType = entityManagerFactory.getMetamodel().managedType( aClass );
} catch ( IllegalArgumentException e ) {
    // happens when aClass isn't a type managed by the persistence unit
}
if ( managedType != null ) {
    config.addAnnotatedClass( aClass );
}

Make sure to use different Configuration instances for each persistence unit. Otherwise, annotated classes would just accumulate and so also the DDL.

I tried it and it worked great - printed two distinct DDLs for two different persistence units.

like image 132
yair Avatar answered Nov 02 '22 18:11

yair