How do you programmatically generate a Hibernate JPA schema?

前端 未结 3 1713
青春惊慌失措
青春惊慌失措 2020-12-22 02:57

I\'d like to use the Hibernate/HBM2DDL schema generation as a starting point for managing my application\'s SQL schema using a tool like Liquibase or Flyway. To assist with

相关标签:
3条回答
  • 2020-12-22 03:11

    After digging through the Hibernate Ant task's source on GitHub, I came up with the following solution:

    /**
     * Uses Hibernate's HBM2DDL {@link SchemaExport} utility to generate SQL
     * database schemas.
     */
    public final class HibernateSchemaPrinter {
        /**
         * A small application driver that calls
         * {@link #printHibernateSchemaToStdout(String, Class)}.
         * 
         * @param args
         *            (unused)
         */
        public static void main(String[] args) {
            printHibernateSchemaToStdout("gov.hhs.cms.bluebutton.data", PostgreSQL95Dialect.class);
        }
    
        /**
         * Prints the Hibernate-/HDM2DDL- auto-generated SQL schema to
         * {@link System#out}.
         * 
         * @param persistenceUnitName
         *            the name of the JPA persistence unit to generate the schema
         *            for
         * @param dialectType
         *            the Hibernate {@link Dialect} type to generate the schema for,
         *            e.g. {@link PostgreSQL95Dialect}
         */
        public static void printHibernateSchemaToStdout(String persistenceUnitName, Class<? extends Dialect> dialectType) {
            Map<Object, Object> properties = new HashMap<>();
            properties.put(AvailableSettings.DIALECT, dialectType.getName());
    
            /*
             * Use a Hibernate EntityManagerFactoryBuilderImpl to create a JPA
             * EntityManagerFactory, then grab the (now populated) Hibernate
             * Metadata instance out of it.
             */
            EntityManagerFactoryBuilderImpl entityManagerFactoryBuilder = new CustomHibernatePersistenceProvider()
                    .getEntityManagerFactoryBuilder(persistenceUnitName, properties);
            entityManagerFactoryBuilder.build();
            Metadata metadata = entityManagerFactoryBuilder.getMetadata();
    
            SchemaExport schemaExport = new SchemaExport();
            schemaExport.setHaltOnError(true);
            schemaExport.setFormat(true);
            schemaExport.setDelimiter(";");
            schemaExport.execute(EnumSet.of(TargetType.STDOUT), Action.CREATE, metadata);
        }
    
        /**
         * A small hack, needed to extract the
         * {@link EntityManagerFactoryBuilderImpl} from
         * {@link HibernatePersistenceProvider}. Taken from the Hibernate Ant task
         * here: <a href=
         * "https://github.com/hibernate/hibernate-tools/blob/321dba082f0cd11a2295063e0cbcf4f34a5b8bdd/main/src/java/org/hibernate/tool/ant/JPAConfigurationTask.java">
         * JPAConfigurationTask.java</a>.
         */
        private static final class CustomHibernatePersistenceProvider extends HibernatePersistenceProvider {
            /**
             * (See overridden method; we're just making it <code>public</code>.)
             * 
             * @param persistenceUnit
             *            (see overridden method)
             * @param properties
             *            (see overridden method)
             * @return (see overridden method)
             */
            public EntityManagerFactoryBuilderImpl getEntityManagerFactoryBuilder(String persistenceUnit,
                    Map<Object, Object> properties) {
                return (EntityManagerFactoryBuilderImpl) getEntityManagerFactoryBuilderOrNull(persistenceUnit, properties);
            }
        }
    }
    

    Takes a bit more code these days, but still works, so good enough.

    0 讨论(0)
  • 2020-12-22 03:22

    If, instead, you want to generate a Liquibase changelog right from the Hibernate metadata, you can use the following code:

    // Create a "connection" to the offline JPA data.
    String url = "jpa:persistence:META-INF/persistence.xml";
    Database jpaDatabase = CommandLineUtils.createDatabaseObject(RESOURCE_ACCESSOR, url, null, null, null, null,
            null, false, false, null, null, null, null, null, null, null);
    
    DiffResult schemaDiff = DiffGeneratorFactory.getInstance().compare(jpaDatabase, null,
            CompareControl.STANDARD);
    DiffToChangeLog diffChangeLogProducer = new DiffToChangeLog(schemaDiff, new DiffOutputControl());
    diffChangeLogProducer.print(System.out);
    
    0 讨论(0)
  • 2020-12-22 03:25

    I see no good reason to not use standard JPA, via

    Persistence.generateSchema(String persistenceUnitName, Map properties);
    

    and that way you don't tie yourself to any particular implementation, and still can get a DDL script by use of the javax.persistence.schema-generation.* properties.

    0 讨论(0)
提交回复
热议问题