/** * Copyright (C) 2014 Premium Minds. * * This file is part of pm-persistence-utils. * * pm-persistence-utils is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * pm-persistence-utils is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with pm-persistence-utils. If not, see <http://www.gnu.org/licenses/>. */ package com.premiumminds.persistence.utils; import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import javax.persistence.PersistenceException; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.internal.FormatStyle; import org.hibernate.engine.jdbc.internal.Formatter; import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl; import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor; import org.hibernate.jpa.boot.internal.PersistenceXmlParser; import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor; import org.hibernate.jpa.boot.spi.ProviderChecker; import org.hibernate.service.ServiceRegistry; import org.hibernate.tool.hbm2ddl.DatabaseMetadata; import org.hibernate.tool.hbm2ddl.SchemaUpdateScript; public class HibernateDDL { private final static Formatter formatter = FormatStyle.DDL.getFormatter(); /** * --create unitName [filename] * --create-drop unitName [filename] * --update unitName jdbcUrl jdbcUsername jdbcPassword [filename] * * @param args usage arguments */ public static void main(String[] args) { if(args.length==0){ System.out.println("Usage: "); System.out.println("\t--create unitName [filename] - Create table commands"); System.out.println("\t--create-drop unitName [filename] - Create table and drop commands"); System.out.println("\t--update unitName jdbcUrl jdbcUsername jdbcPassword [filename] - Alter table commands based on your database"); System.out.println("\n\t[filename] is the name of the file where to write (it's optional)"); } else { if("--create".equals(args[0].toLowerCase())) createCommand(args); if("--create-drop".equals(args[0].toLowerCase())) createDropCommand(args); if("--update".equals(args[0].toLowerCase())) updateCommand(args); } } protected static void updateCommand(String[] args) { String unitName, filename=null, url, username, password; if(args.length<5) System.out.println("Expected unitName jdbcUrl jdbcUsername jdbcPassword [filename]"); else { unitName = args[1]; url = args[2]; username = args[3]; password = args[4]; if(args.length>5) filename = args[5]; Configuration config = getConfiguration(unitName); Dialect dialect = Dialect.getDialect(config.getProperties()); try { Connection conn = DriverManager.getConnection(url, username, password); DatabaseMetadata meta = new DatabaseMetadata(conn, dialect, config, true); List<SchemaUpdateScript> updateScriptList = config.generateSchemaUpdateScriptList(dialect, meta); String[] updateSQL = SchemaUpdateScript.toStringArray(updateScriptList); stringToStream(updateSQL, filename); } catch (SQLException e) { e.printStackTrace(); } } } protected static EntityManagerFactoryBuilderImpl getEntityManagerFactoryBuilderOrNull(String persistenceUnitName, Map<String, Object> properties) { return getEntityManagerFactoryBuilderOrNull( persistenceUnitName, properties, null ); } protected static EntityManagerFactoryBuilderImpl getEntityManagerFactoryBuilderOrNull(String persistenceUnitName, Map<String, Object> properties, ClassLoader providedClassLoader) { final Map<String, Object> integration = wrap( properties ); final List<ParsedPersistenceXmlDescriptor> units; try { units = PersistenceXmlParser.locatePersistenceUnits( integration ); } catch (Exception e) { throw new PersistenceException( "Unable to locate persistence units", e ); } if ( persistenceUnitName == null && units.size() > 1 ) { throw new PersistenceException( "No name provided and multiple persistence units found" ); } for ( ParsedPersistenceXmlDescriptor persistenceUnit : units ) { final boolean matches = persistenceUnitName == null || persistenceUnit.getName().equals( persistenceUnitName ); if ( !matches ) { continue; } // See if we (Hibernate) are the persistence provider if ( ! ProviderChecker.isProvider( persistenceUnit, properties ) ) { continue; } return getEntityManagerFactoryBuilder( persistenceUnit, integration, providedClassLoader ); } return null; } protected static EntityManagerFactoryBuilderImpl getEntityManagerFactoryBuilder(PersistenceUnitDescriptor persistenceUnitDescriptor, Map<String, Object> integration, ClassLoader providedClassLoader) { return new EntityManagerFactoryBuilderImpl( persistenceUnitDescriptor, integration, providedClassLoader ); } protected static Map<String, Object> wrap(Map<String, Object> properties) { return properties == null ? Collections.<String, Object>emptyMap() : Collections.unmodifiableMap( properties ); } protected static void createDropCommand(String[] args) { String unitName; String filename=null; if(args.length<2) System.out.println("Expected unitName"); else { unitName = args[1]; if(args.length>2) filename = args[2]; Configuration config = getConfiguration(unitName); String[] dropSQL = config.generateDropSchemaScript(Dialect.getDialect(config.getProperties())); String[] createSQL = config.generateSchemaCreationScript(Dialect.getDialect(config.getProperties())); stringToStream(concat(dropSQL, createSQL), filename); } } protected static void createCommand(String[] args) { String unitName; String filename=null; if(args.length<2) System.out.println("Expected unitName"); else { unitName = args[1]; if(args.length>2) filename = args[2]; Configuration config = getConfiguration(unitName); String[] createSQL = config.generateSchemaCreationScript(Dialect.getDialect(config.getProperties())); stringToStream(createSQL, filename); } } protected static Configuration getConfiguration(String unitName){ EntityManagerFactoryBuilderImpl entityManagerFactoryBuilder = getEntityManagerFactoryBuilderOrNull(unitName, null); ServiceRegistry serviceRegistry = entityManagerFactoryBuilder.buildServiceRegistry(); Configuration config = entityManagerFactoryBuilder.buildHibernateConfiguration(serviceRegistry); return config; } protected static void stringToStream(String[] sql, String filename){ PrintWriter writer; try { if(filename==null) writer = new PrintWriter(System.out); else writer = new PrintWriter(new File(filename)); for (String string : sql) { writer.print(formatter.format(string) + ";\n"); } writer.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } public static <T> T[] concat(T[] first, T[] second) { T[] result = Arrays.copyOf(first, first.length + second.length); System.arraycopy(second, 0, result, first.length, second.length); return result; } }