2015-11-13 94 views
5

我尝试使用这个类:休眠5.生成SQL DDL文件到

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

显然配置类不能使用。我们必须使用MetadataSources类来添加注释类。

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

嗨felix,我遇到了类似的问题,并找到了解决办法。也许它也可以帮助你: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); 
}