2016-01-20 5 views
0

Il y a deux ans, je travaillais sur un projet en utilisant:Générer automatiquement le schéma de données de JPA 2.1 classes d'entités annotées sans connexion de base de données

  • printemps 4.0.3.RELEASE
  • JPA 2.0
  • mise en veille prolongée 4.2 .7.Final
  • java 1.6.X

Ce projet a une tâche Maven hibernate3-maven-plugin qui nous permettent de générer un schéma de base de données w sans aucune connexion à une base de données (MySQL).

Maintenant, nous mettez à niveau ce projet avec:

  • java 1.8
  • JPA 2.1
  • printemps 4.2.4.RELEASE
  • mise en veille prolongée 5.0.6.Final

I comprendre que hibernate3-maven-plugin ne fonctionne pas sur JPA 2.1 et hibernate> 4.3.

Toute la solution que j'ai trouvée nécessite une connexion à une base de données.

Par exemple: Auto generate data schema from JPA annotated entity classes.

Est-ce que quelqu'un sait comment générer un schéma de base de données hors ligne? Tout ce que j'ai est un persistence.xml avec toutes les classes Entity listées.

+0

Cela n'a rien à voir avec le printemps ici, s'il vous plaît enlever l'étiquette – chokdee

Répondre

0

j'ai pu mélanger votre solution Hibernate avec JPA2.1:

Je suis maintenant en mesure d'ajouter les classes d'entités du persistence.xml

De cette façon, je peux générer le fichier sql à l'extérieur du pot où les entités sont situées.

Ceci est une solution temporaire jusqu'à mise en veille prolongée Réparer ce bug

Merci pour votre aide.

/** 
* 
*/ 
package com.stackoverflow.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(); 
    } 

} 
0

Comme l'autre question, vous pouvez utiliser hbm2ddl et une base de données intégrée pour fournir une connexion.

Pour la base de données en utilisant H2 exemple (nécessitent h2, scannotation, veille prolongée et io commun):

package com.stackoverflow; 
import java.io.File; 
import java.io.FileWriter; 
import java.io.InputStream; 
import java.net.URL; 
import java.util.Set; 
import javax.persistence.Entity; 
import org.apache.commons.io.IOUtils; 
import org.hibernate.cfg.Configuration; 
import org.hibernate.cfg.Environment; 
import org.hibernate.connection.DriverManagerConnectionProvider; 
import org.hibernate.dialect.PostgreSQLDialect; 
import org.hibernate.tool.hbm2ddl.SchemaExport; 
import org.scannotation.AnnotationDB; 

public class ExportShema { 

    private static final String OUTPUT_SQL_FILE = "target/database.sql"; 
    private static final String INIT_FILE = "init.sql"; 
    private static final String DB_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"; 
    private static final String DB_USERNAME = "sa"; 
    private static final String DB_PASSWORD = ""; 
    private static final File HBM_DIRECTORY = new File("src/main/resources/com/stackoverflow/domain/"); 

    public static void main(final String[] args) throws Exception { 
     final Configuration cfg = new Configuration(); 
     cfg.setProperty(Environment.CONNECTION_PROVIDER, DriverManagerConnectionProvider.class.getName()); 
     //for postgrest schema 
     cfg.setProperty(Environment.DIALECT, PostgreSQLDialect.class.getName()); 
     cfg.setProperty(Environment.URL, DB_URL); 
     cfg.setProperty(Environment.USER, DB_USERNAME); 
     cfg.setProperty(Environment.PASS, DB_PASSWORD); 

     //If you have HBM + annotated class 
     cfg.addDirectory(HBM_DIRECTORY); 

     final AnnotationDB db = new AnnotationDB(); 
     db.scanArchives(new URL("file:target/classes/")); 
     final Set<String> clazzNames = db.getAnnotationIndex().get(Entity.class.getName()); 
     for (final String clazzName : clazzNames) { 
      cfg.addAnnotatedClass(Class.forName(clazzName)); 
     } 

     final SchemaExport exporter = new SchemaExport(cfg); 
     exporter.setOutputFile(OUTPUT_SQL_FILE); 
     exporter.setDelimiter(";"); 
     exporter.setFormat(true); 
     exporter.create(false, true); 

     try (final InputStream init_file = ExportShema.class.getResourceAsStream(INIT_FILE)) { 
      if (init_file != null) { 
       final File output = new File(OUTPUT_SQL_FILE); 
       try (final FileWriter fw = new FileWriter(output, true)) { 
        final String eol = System.getProperty("line.separator"); 
        fw.append(eol + eol); 
        fw.append(IOUtils.toString(init_file)); 
       } 
      } 
     } 
} 
} 

vous pouvez le faire dans un test unitaire ou créer un processeur d'annotation.

+0

je suis tombé sur cette solution, mais je ne savais pas si le SQL généré est 100U Mysql conforme. Savez-vous où je peux trouver cette information? –

+0

Cela dépendra de l'implémentation de la classe Mysql Dialect. Je l'utilise pour postgresql et ça marche bien. – JEY

3

Je suis votre idée d'utiliser h2 avec le dialecte Mysql mais en utilisant JPA Persistence.generateSchema(...).

Il ne fonctionne, sauf toutes les commandes ne sont pas séparés par une demi-colonne ...

Comment cela peut-il été fait en utilisant JPA 2.1?

Sinon, je vais passer à votre solution.

import java.util.Properties; 

import javax.persistence.Persistence; 
import javax.persistence.PersistenceException; 

import org.hibernate.jpa.AvailableSettings; 

/** 
* Generate DDL with hibernate 4+/5: 
* http://stackoverflow.com/questions/27314165/generate-ddl-script-at-maven-build-with-hibernate4-jpa-2-1/27314166#27314166 
* @author dmary 
* 
*/ 
public class Jpa21SchemaExport { 

    /** 
    * 
    */ 
    public Jpa21SchemaExport() { 
     // TODO Auto-generated constructor stub 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     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); 

     persistenceProperties.setProperty(AvailableSettings.JDBC_DRIVER,"org.h2.Driver"); 
     persistenceProperties.setProperty(AvailableSettings.JDBC_URL, "jdbc:h2:mem:export"); 
     persistenceProperties.setProperty(AvailableSettings.JDBC_USER, "sa"); 
     persistenceProperties.setProperty(AvailableSettings.JDBC_PASSWORD, ""); 

     persistenceProperties.setProperty(org.hibernate.cfg.AvailableSettings.DIALECT, "com.wiztivi.sdk.persistence.MySQL5InnoDBUTF8Dialect"); 

     try 
     { 
      Persistence.generateSchema(persistenceUnitName, persistenceProperties); 
     } catch (PersistenceException pe) 
     { 
      System.err.println("DDL generation failed: "); 
      pe.printStackTrace(System.err); 
     } 
    } 
+0

N'ayant pas de point-virgule est un bug connu: https://hibernate.atlassian.net/browse/HHH-10278 –

+0

Étrange que l'application. n'existe pas sans 'System.exit (0)' –

+0

La meilleure solution est la suivante: // générer sql avec virgule - solution de contournement pour HHH-10278 chaîne systemLineSeparator = System.getProperty ("line.separator"); System.setProperty ("line.separator", ';' + systemLineSeparator); Persistence.generateSchema (persistenceUnitName, persistenceProperties); – blacky