2015-11-13 5 views
5

में एसक्यूएल DDL उत्पन्न मैं इस वर्ग के उपयोग करने की कोशिश:हाइबरनेट 5. फ़ाइल

Hibernate/JPA: Check generated sql before updating DB Schema (like .NET EF migrations)

मैं निम्नलिखित कोड:

package com.mypackage.jpa.util; 

import java.io.File; 
import java.net.URL; 
import java.util.ArrayList; 
import java.util.List; 

import org.hibernate.cfg.Configuration; 
import org.hibernate.tool.hbm2ddl.SchemaExport; 

public class SchemaGenerator { 

    private Configuration cfg; 

    public static void main(String[] args) throws Exception { 

     File f = new File("."); 
     String directory = f.getAbsoluteFile() + "/src/main/resources/ddl/generated/"; 

     String packageName[] = { "com.mypackage.jpa", "com.mypackage.jpa.legacy", "com.mypackage.jpa.local", 
       "com.mypackage.jpa.local.impl" }; 

     SchemaGenerator gen = new SchemaGenerator(packageName); 
     gen.generate(Dialect.MYSQL, directory); 

    } 

    @SuppressWarnings("rawtypes") 
    public SchemaGenerator(String[] packagesName) throws Exception { 
     cfg = new Configuration(); 
     cfg.setProperty("hibernate.hbm2ddl.auto", "create"); 

     for (String packageName : packagesName) { 
      for (Class clazz : getClasses(packageName)) { 
       cfg.addAnnotatedClass(clazz); 
      } 
     } 
    } 

    @SuppressWarnings("rawtypes") 
    private List<Class> getClasses(String packageName) throws Exception { 
     File directory = null; 
     try { 
      ClassLoader cld = getClassLoader(); 
      URL resource = getResource(packageName, cld); 
      directory = new File(resource.getFile()); 
     } catch (NullPointerException ex) { 
      throw new ClassNotFoundException(packageName + " (" + directory + ") does not appear to be a valid package"); 
     } 
     return collectClasses(packageName, directory); 
    } 

    private ClassLoader getClassLoader() throws ClassNotFoundException { 
     ClassLoader cld = Thread.currentThread().getContextClassLoader(); 
     if (cld == null) { 
      throw new ClassNotFoundException("Can't get class loader."); 
     } 
     return cld; 
    } 

    private URL getResource(String packageName, ClassLoader cld) throws ClassNotFoundException { 
     String path = packageName.replace('.', '/'); 
     URL resource = cld.getResource(path); 
     if (resource == null) { 
      throw new ClassNotFoundException("No resource for " + path); 
     } 
     return resource; 
    } 

    @SuppressWarnings("rawtypes") 
    private List<Class> collectClasses(String packageName, File directory) throws ClassNotFoundException { 
     List<Class> classes = new ArrayList<>(); 
     if (directory.exists()) { 
      String[] files = directory.list(); 
      for (String file : files) { 
       if (file.endsWith(".class")) { 
        // removes the .class extension 
        classes.add(Class.forName(packageName + '.' + file.substring(0, file.length() - 6))); 
       } 
      } 
     } else { 
      throw new ClassNotFoundException(packageName + " is not a valid package"); 
     } 
     return classes; 
    } 

    private void generate(Dialect dialect, String directory) { 
     cfg.setProperty("hibernate.dialect", dialect.getDialectClass()); 
     SchemaExport export = new SchemaExport(cfg); 
     export.setDelimiter(";"); 
     export.setOutputFile(directory + "ddl_" + dialect.name().toLowerCase() + ".sql"); 
     export.setFormat(true); 
     export.execute(true, false, false, false); 
    } 

    private static enum Dialect { 
     ORACLE("org.hibernate.dialect.Oracle10gDialect"), MYSQL("org.hibernate.dialect.MySQLDialect"), HSQL(
       "org.hibernate.dialect.HSQLDialect"), H2("org.hibernate.dialect.H2Dialect"); 

     private String dialectClass; 

     private Dialect(String dialectClass) { 
      this.dialectClass = dialectClass; 
     } 

     public String getDialectClass() { 
      return dialectClass; 
     } 
    } 
} 

और मैं निम्नलिखित त्रुटि मिलती है:

Exception in thread "main" java.lang.UnsupportedOperationException: Attempt to use unsupported SchemaExport constructor accepting org.hibernate.cfg.Configuration; one of the forms accepting org.hibernate.boot.spi.MetadataImplementor should be used instead at org.hibernate.tool.hbm2ddl.SchemaExport.(SchemaExport.java:250) at cu.x.util.SchemaGenerator.generate(SchemaGenerator.java:116) at cu.x.util.SchemaGenerator.main(SchemaGenerator.java:32) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

मैं अपना कोड निम्नलिखित के साथ बदलता हूं:

ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build(); 
MetadataImplementor metadataImplementor = (MetadataImplementor) 
     new MetadataSources(serviceRegistry).buildMetadata(); 
SchemaExport export = new SchemaExport(metadataImplementor); 

लेकिन यह एक खाली .sql फ़ाइल उत्पन्न करता है। मैं एनोटेटेड कक्षाओं का उपयोग कर रहा हूँ। क्या हो रहा है?

+0

हाँ, मेरी मूल भाषा स्पेनिश है। मैं पूरी तरह से अंग्रेजी पढ़ सकता हूं लेकिन बुरी तरह लिख रहा हूं। मेरे काम में केवल अंग्रेजी में पढ़ना, लिखना या बोलना जरूरी नहीं है। – felix

+0

मेरी माफ़ी, जो मेरे संपादन के कारण पर टिप्पणी करने का इरादा था। मैं आपकी अंग्रेजी का अनावश्यक रूप से अपमान करने की कोशिश नहीं कर रहा था। – leigero

उत्तर

6

स्पष्ट रूप से कॉन्फ़िगरेशन क्लास का उपयोग नहीं किया जा सकता है। एनोटेटेड कक्षाओं को जोड़ने के लिए हमें मेटाडाटा स्रोत स्रोत का उपयोग करना होगा।

private void generate(Dialect dialect, String directory, String[] packagesName) throws Exception { 

    MetadataSources metadata = new MetadataSources(
      new StandardServiceRegistryBuilder() 
        .applySetting("hibernate.dialect", dialect.getDialectClass()) 
        .build()); 

    for (String packageName : packagesName) { 
     log.info("packageName: " + packageName); 
     for (Class clazz : getClasses(packageName)) { 
      log.info("Class: " + clazz); 
      metadata.addAnnotatedClass(clazz); 
     } 
    } 

    SchemaExport export = new SchemaExport(
      (MetadataImplementor) metadata.buildMetadata() 
    ); 

    export.setDelimiter(";"); 
    export.setOutputFile(directory + "ddl_" + dialect.name().toLowerCase() + ".sql"); 
    export.setFormat(true); 
    export.execute(true, false, false, false); 
} 
+0

हाय फ़ेलिक्स, मैं एक समान समस्या में भाग गया और एक समाधान भी मिला। शायद यह आपको भी मदद करता है: http://stackoverflow.com/a/41894432/974186 –

1

फेलिक्स का समाधान हाइबरनेट 5.2

यहाँ पर अब और काम नहीं करते एक संस्करण है जो सी संगत निजी शून्य उत्पन्न (कक्षा बोली, स्ट्रिंग निर्देशिका, स्ट्रिंग ... packagesName) है अपवाद {फेंकता

MetadataSources metadata = new MetadataSources(
      new StandardServiceRegistryBuilder() 
        .applySetting("hibernate.dialect", dialect.getName()) 
        .build()); 

    for (String packageName : packagesName) { 
     LOG.info("packageName: " + packageName); 
     for (Class clazz : getClasses(packageName)) { 
      LOG.info("Class: " + clazz); 
      metadata.addAnnotatedClass(clazz); 
     } 
    } 

    MetadataImplementor metadataImplementor = (MetadataImplementor) metadata.buildMetadata(); 
    SchemaExport export = new SchemaExport(); 

    export.setDelimiter(";"); 
    String filename = directory + "ddl_" + dialect.getSimpleName().toLowerCase() + ".sql"; 
    export.setOutputFile(filename); 
    export.setFormat(true); 

    //can change the output here 
    EnumSet<TargetType> enumSet = EnumSet.of(TargetType.STDOUT); 
    export.execute(enumSet, SchemaExport.Action.CREATE, metadataImplementor); 
} 
संबंधित मुद्दे