Monday, September 5, 2016

Hibernate 4 - publish changes / updates to the schema with entities in Spring JavaConfig

package com.mycompany.domain.test;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.hibernate.MappingException;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.cfg.Configuration;
import org.hibernate.metamodel.MetadataSources;
import org.hibernate.metamodel.source.MetadataImplementor;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tool.hbm2ddl.SchemaUpdate;

public class JpaSchemaExport {
   
   private static final Logger LOGGER = Logger.getLogger(JpaSchemaExport.class);
     
   public static void main(String[] args) throws MappingException, IOException, ClassNotFoundException {
      BasicConfigurator.configure();
      Configuration c = new Configuration();
      Class[] clzzs = getClasses("com.mycompany.domain.entity");
      for (int i = 0; i < clzzs.length; i++) {
         c.addAnnotatedClass(clzzs[i]);
      }
      Properties hibernateProperties = new Properties();
      hibernateProperties.put("hibernate.connection.driver_class","oracle.jdbc.OracleDriver");
      hibernateProperties.put("hibernate.connection.url","jdbc:oracle:thin:@");
      hibernateProperties.put("hibernate.connection.username","scott");
      hibernateProperties.put("hibernate.connection.password","secret99");
      hibernateProperties.put("hibernate.show_sql", true);
      hibernateProperties.put("hibernate.dialect","org.hibernate.dialect.Oracle10gDialect");
      hibernateProperties.put("hibernate.format_sql", true);
      hibernateProperties.put("connection.pool_size", 3);
      hibernateProperties.put("current_session_context_class", "thread");
      hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
      c.addProperties(hibernateProperties);
      
      StandardServiceRegistryBuilder registry = new StandardServiceRegistryBuilder();
      registry.applySettings(c.getProperties());

      ServiceRegistry serviceRegistry = registry.build();
      MetadataImplementor metadata = (MetadataImplementor) new MetadataSources(serviceRegistry).buildMetadata();

      SchemaUpdate schemaExport = new SchemaUpdate(serviceRegistry, c);

      // use this line when exporting the whole DDL 
      //SchemaExport schemaExport = new SchemaExport(serviceRegistry,c);
      File f = new File("export.sql");  
      schemaExport.setOutputFile(f.getAbsolutePath());
      System.err.println(f.getAbsolutePath());
      schemaExport.execute(true, false);
      

      if (schemaExport.getExceptions().size() > 0) {
         Iterator iterator = schemaExport.getExceptions().iterator();
         int cnt = 1;
         LOGGER.warn(schemaExport.getExceptions().size() + " errors occurred while performing .");
         while (iterator.hasNext()) {
             LOGGER.error("Error #" + cnt + ": " + iterator.next().toString());
         }

     }
      
      ( (StandardServiceRegistryImpl) serviceRegistry ).destroy();
  }
  
  /**
   * Scans all classes accessible from the context class loader which belong to the given package and subpackages.
   *
   * @param packageName The base package
   * @return The classes
   * @throws ClassNotFoundException
   * @throws IOException
   */
  private static Class[] getClasses(String packageName)
          throws ClassNotFoundException, IOException {
      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      assert classLoader != null;
      String path = packageName.replace('.', '/');
      Enumeration resources = classLoader.getResources(path);
      List dirs = new ArrayList();
      while (resources.hasMoreElements()) {
          URL resource = resources.nextElement();
          dirs.add(new File(resource.getFile()));
      }
      ArrayList classes = new ArrayList();
      for (File directory : dirs) {
          classes.addAll(findClasses(directory, packageName));
      }
      return classes.toArray(new Class[classes.size()]);
  }

  /**
   * Recursive method used to find all classes in a given directory and subdirs.
   *
   * @param directory   The base directory
   * @param packageName The package name for classes found inside the base directory
   * @return The classes
   * @throws ClassNotFoundException
   */
  private static List findClasses(File directory, String packageName) throws ClassNotFoundException {
      List classes = new ArrayList();
      if (!directory.exists()) {
          return classes;
      }
      File[] files = directory.listFiles();
      for (File file : files) {
          if (file.isDirectory()) {
              assert !file.getName().contains(".");
              classes.addAll(findClasses(file, packageName + "." + file.getName()));
          } else if (file.getName().endsWith(".class")) {
              classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
          }
      }
      return classes;
  }  
}

No comments:

Post a Comment