从JPA 2.1带注释的实体类自动生成数据模式,无需数据库连接

从JPA 2.1带注释的实体类自动生成数据模式,无需数据库连接

问题描述:

两年前,我正在使用以下项目开展项目:

Two years ago I was working on a project using:


  • spring 4.0.3.RELEASE

  • jpa 2.0

  • hibernate 4.2.7.Final

  • java 1.6.X

  • spring 4.0.3.RELEASE
  • jpa 2.0
  • hibernate 4.2.7.Final
  • java 1.6.X

这个项目有一个maven任务hibernate3-maven-plugin,它允许我们生成一个数据库模式,而不需要连接数据库(MySQL)。

This project has a maven task hibernate3-maven-plugin which allow us to generate a database schema without any connection to a database (MySQL).

现在我们正在升级这个项目:

Now we are upgrading this project with:


  • java 1.8

  • jpa 2.1

  • spring 4.2.4.RELEASE

  • hibernate 5.0.6.Final

  • java 1.8
  • jpa 2.1
  • spring 4.2.4.RELEASE
  • hibernate 5.0.6.Final

我知道hibernate3-maven-plugin在JPA 2.1和hibernate> 4.3上不起作用。

I understand that hibernate3-maven-plugin does not work on JPA 2.1 and hibernate > 4.3.

我找到的所有解决方案都需要连接到数据库。

All the solution I have found need a connection to a database.

例如:从JPA带注释的实体类中自动生成数据模式

有谁知道如何g离线使用数据库模式?
我所拥有的是一个包含所有实体类的persistence.xml。

Does anyone know how to generate a database schema offline? All I have is a persistence.xml with all the Entity classes listed.

我能够混合你的使用JPA2.1的Hibernate解决方案:

I was able to mix your Hibernate solution with JPA2.1:

我现在能够从persistence.xml中添加实体类

I am now able to add the entity classes from the persistence.xml

这样我就可以在实体所在的jar之外生成SQl文件。

This way I can generate the SQl file outside the jar where the entities are located.

这是一个临时解决方案,直到hibernate修复此 bug

This is a temporary solution till hibernate fix this bug

感谢您的帮助。

/**
 * 
 */
package com.*.common.util.schema;

import java.io.IOException;
import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.Metamodel;

import org.hibernate.boot.MetadataBuilder;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.tool.hbm2ddl.SchemaExport;

import org.hibernate.dialect.MySQL5InnoDBDialect;

/**
 *
 */
public class JPA21Hibernate5ExportSchema {

    private static final String JDBC_DRIVER = "org.h2.Driver";
    private static final String JDBC_URL = "jdbc:h2:mem:export;DB_CLOSE_DELAY=-1";
    private static final String JDBC_USERNAME = "sa";
    private static final String JDBC_PASSWORD = "";

    /**
     * 
     */
    public JPA21Hibernate5ExportSchema() {

    }

    public static void main(String[] args) {
        try {
            JPA21Hibernate5ExportSchema hes = new JPA21Hibernate5ExportSchema();
            hes.export(args[0], args[1]);
            System.exit(0);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

    }

    public void export(String persistenceUnitName, String sqlFile) throws IOException, ClassNotFoundException {

        final BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();
        final MetadataSources metadataSources = new MetadataSources(bsr);

        final StandardServiceRegistryBuilder srrBuilder = new StandardServiceRegistryBuilder(bsr)
                .applySetting(Environment.CONNECTION_PROVIDER, DriverManagerConnectionProviderImpl.class.getName())
                .applySetting(Environment.DIALECT, MySQL5InnoDBDialect.class.getName())
                .applySetting(Environment.URL, JDBC_URL).applySetting(Environment.USER, JDBC_USERNAME)
                .applySetting(Environment.PASS, JDBC_PASSWORD);

        // Use the persistence metamodel to retrieve the Entities classes
        Metamodel metamodel = this.getMetamodel(persistenceUnitName);
        for (final ManagedType<?> managedType : metamodel.getManagedTypes()) {
            metadataSources.addAnnotatedClass(managedType.getJavaType());
        }

        final StandardServiceRegistry ssr = (StandardServiceRegistry) srrBuilder.build();
        final MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder(ssr);

        final SchemaExport exporter = new SchemaExport((MetadataImplementor) metadataBuilder.build());
        exporter.setOutputFile(sqlFile);
        exporter.setDelimiter(";");
        exporter.setFormat(true);
        exporter.create(false, true);

    }

    /**
     * Retrieve the JPA metamodel from the persistence unit name
     * 
     * @param persistenceUnitName
     * @return
     */
    private Metamodel getMetamodel(String persistenceUnitName) {
        final Properties persistenceProperties = new Properties();
        persistenceProperties.setProperty(AvailableSettings.JDBC_DRIVER, JDBC_DRIVER);
        persistenceProperties.setProperty(AvailableSettings.JDBC_URL, JDBC_URL);
        persistenceProperties.setProperty(AvailableSettings.JDBC_USER, "sa");
        persistenceProperties.setProperty(AvailableSettings.JDBC_PASSWORD, "");
        persistenceProperties.setProperty(org.hibernate.cfg.AvailableSettings.DIALECT,
                MySQL5InnoDBDialect.class.getName());

        final EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName,
                persistenceProperties);
        return emf.getMetamodel();
    }

}