HHH-5996 - Wire in JdbcServices into SchemaUpdateTask, SchemaExportTask, SchemaValidatorTask, HibernateService.dropSchema(), HibernateService.createSchema()

This commit is contained in:
Steve Ebersole 2011-03-30 16:58:15 -05:00
parent 3e22ef111c
commit ee2dd0ddf5
12 changed files with 610 additions and 279 deletions

View File

@ -388,16 +388,16 @@ public final class SessionFactoryImpl
LOG.debugf("Instantiated session factory"); LOG.debugf("Instantiated session factory");
if ( settings.isAutoCreateSchema() ) { if ( settings.isAutoCreateSchema() ) {
new SchemaExport( getJdbcServices(), cfg ).create( false, true ); new SchemaExport( serviceRegistry, cfg ).create( false, true );
} }
if ( settings.isAutoUpdateSchema() ) { if ( settings.isAutoUpdateSchema() ) {
new SchemaUpdate( getJdbcServices(), cfg ).execute( false, true ); new SchemaUpdate( serviceRegistry, cfg ).execute( false, true );
} }
if ( settings.isAutoValidateSchema() ) { if ( settings.isAutoValidateSchema() ) {
new SchemaValidator( getJdbcServices(), cfg ).validate(); new SchemaValidator( serviceRegistry, cfg ).validate();
} }
if ( settings.isAutoDropSchema() ) { if ( settings.isAutoDropSchema() ) {
schemaExport = new SchemaExport( getJdbcServices(), cfg ); schemaExport = new SchemaExport( serviceRegistry, cfg );
} }
currentSessionContext = buildCurrentSessionContext(); currentSessionContext = buildCurrentSessionContext();

View File

@ -0,0 +1,85 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program 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 this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.hbm2ddl;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import org.jboss.logging.Logger;
import org.hibernate.HibernateLogger;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
/**
* @author Steve Ebersole
*/
class DatabaseExporter implements Exporter {
private static final HibernateLogger LOG = Logger.getMessageLogger( HibernateLogger.class, DatabaseExporter.class.getName() );
private final ConnectionHelper connectionHelper;
private final SqlExceptionHelper sqlExceptionHelper;
private final Connection connection;
private final Statement statement;
public DatabaseExporter(ConnectionHelper connectionHelper, SqlExceptionHelper sqlExceptionHelper) throws SQLException {
this.connectionHelper = connectionHelper;
this.sqlExceptionHelper = sqlExceptionHelper;
connectionHelper.prepare( true );
connection = connectionHelper.getConnection();
statement = connection.createStatement();
}
@Override
public boolean acceptsImportScripts() {
return true;
}
@Override
public void export(String string) throws Exception {
statement.executeUpdate( string );
try {
SQLWarning warnings = statement.getWarnings();
if ( warnings != null) {
sqlExceptionHelper.logAndClearWarnings( connection );
}
}
catch( SQLException e ) {
LOG.unableToLogSqlWarnings( e );
}
}
@Override
public void release() throws Exception {
try {
statement.close();
}
finally {
connectionHelper.release();
}
}
}

View File

@ -0,0 +1,33 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program 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 this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.hbm2ddl;
/**
* @author Steve Ebersole
*/
interface Exporter {
public boolean acceptsImportScripts();
public void export(String string) throws Exception;
public void release() throws Exception;
}

View File

@ -0,0 +1,54 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program 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 this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.hbm2ddl;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author Steve Ebersole
*/
class FileExporter implements Exporter {
private final FileWriter writer;
public FileExporter(String outputFile) throws IOException {
this.writer = new FileWriter( outputFile );
}
@Override
public boolean acceptsImportScripts() {
return false;
}
@Override
public void export(String string) throws Exception {
writer.write( string + '\n');
}
@Override
public void release() throws Exception {
writer.flush();
writer.close();
}
}

View File

@ -0,0 +1,39 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program 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 this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.hbm2ddl;
import org.hibernate.HibernateException;
/**
* @author Steve Ebersole
*/
public class ImportScriptException extends HibernateException {
public ImportScriptException(String s) {
super( s );
}
public ImportScriptException(String string, Throwable root) {
super( string, root );
}
}

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC. * distributed under license by Red Hat Inc.
* *
* This copyrighted material is made available to anyone wishing to use, modify, * This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,14 +20,12 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.tool.hbm2ddl; package org.hibernate.tool.hbm2ddl;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@ -40,9 +38,11 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import org.jboss.logging.Logger;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.HibernateLogger; import org.hibernate.HibernateLogger;
import org.hibernate.JDBCException;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.NamingStrategy;
@ -55,106 +55,136 @@ import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.internal.util.ConfigHelper; import org.hibernate.internal.util.ConfigHelper;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.internal.BasicServiceRegistryImpl; import org.hibernate.service.internal.BasicServiceRegistryImpl;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.jboss.logging.Logger;
/** /**
* Commandline tool to export table schema to the database. This class may also be called from inside an application. * Commandline tool to export table schema to the database. This class may also be called from inside an application.
* *
* @author Daniel Bradby * @author Daniel Bradby
* @author Gavin King * @author Gavin King
* @author Steve Ebersole
*/ */
public class SchemaExport { public class SchemaExport {
private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, SchemaExport.class.getName()); private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, SchemaExport.class.getName());
private ConnectionHelper connectionHelper;
private String[] dropSQL;
private String[] createSQL;
private String outputFile = null;
private String importFiles;
private Dialect dialect;
private String delimiter;
private final List exceptions = new ArrayList();
private boolean haltOnError = false;
private Formatter formatter;
private SqlStatementLogger sqlStatementLogger;
private static final String DEFAULT_IMPORT_FILE = "/import.sql"; private static final String DEFAULT_IMPORT_FILE = "/import.sql";
public static enum Type {
CREATE,
DROP,
NONE,
BOTH;
public boolean doCreate() {
return this == BOTH || this == CREATE;
}
public boolean doDrop() {
return this == BOTH || this == DROP;
}
}
private final ConnectionHelper connectionHelper;
private final SqlStatementLogger sqlStatementLogger;
private final SqlExceptionHelper sqlExceptionHelper;
private final String[] dropSQL;
private final String[] createSQL;
private final String importFiles;
private final List<Exception> exceptions = new ArrayList<Exception>();
private Formatter formatter;
private String outputFile = null;
private String delimiter;
private boolean haltOnError = false;
public SchemaExport(ServiceRegistry serviceRegistry, Configuration configuration) {
this.connectionHelper = new SuppliedConnectionProviderConnectionHelper(
serviceRegistry.getService( ConnectionProvider.class )
);
this.sqlStatementLogger = serviceRegistry.getService( JdbcServices.class ).getSqlStatementLogger();
this.formatter = ( sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter();
this.sqlExceptionHelper = serviceRegistry.getService( JdbcServices.class ).getSqlExceptionHelper();
this.importFiles = ConfigurationHelper.getString(
Environment.HBM2DDL_IMPORT_FILES,
configuration.getProperties(),
DEFAULT_IMPORT_FILE
);
final Dialect dialect = serviceRegistry.getService( JdbcServices.class ).getDialect();
this.dropSQL = configuration.generateDropSchemaScript( dialect );
this.createSQL = configuration.generateSchemaCreationScript( dialect );
}
/** /**
* Create a schema exporter for the given Configuration * Create a schema exporter for the given Configuration
* *
* @param cfg The configuration from which to build a schema export. * @param configuration The configuration from which to build a schema export.
* @throws HibernateException Indicates problem preparing for schema export. * @throws HibernateException Indicates problem preparing for schema export.
*/ */
public SchemaExport(Configuration cfg) throws HibernateException { public SchemaExport(Configuration configuration) {
this( cfg, cfg.getProperties() ); this( configuration, configuration.getProperties() );
}
/**
* Create a schema exporter for the given Configuration and given settings
*
* @param cfg The configuration from which to build a schema export.
* @param jdbcServices The jdbc services
* @throws HibernateException Indicates problem preparing for schema export.
*/
public SchemaExport(JdbcServices jdbcServices, Configuration cfg) throws HibernateException {
dialect = jdbcServices.getDialect();
connectionHelper = new SuppliedConnectionProviderConnectionHelper( jdbcServices.getConnectionProvider() );
dropSQL = cfg.generateDropSchemaScript( dialect );
createSQL = cfg.generateSchemaCreationScript( dialect );
sqlStatementLogger = jdbcServices.getSqlStatementLogger();
formatter = ( sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter();
importFiles = ConfigurationHelper.getString(
Environment.HBM2DDL_IMPORT_FILES, cfg.getProperties(),
DEFAULT_IMPORT_FILE
);
} }
/** /**
* Create a schema exporter for the given Configuration, with the given * Create a schema exporter for the given Configuration, with the given
* database connection properties. * database connection properties.
* *
* @param cfg The configuration from which to build a schema export. * @param configuration The configuration from which to build a schema export.
* @param properties The properties from which to configure connectivity etc. * @param properties The properties from which to configure connectivity etc.
* @throws HibernateException Indicates problem preparing for schema export. * @throws HibernateException Indicates problem preparing for schema export.
* *
* @deprecated properties may be specified via the Configuration object * @deprecated properties may be specified via the Configuration object
*/ */
@Deprecated @Deprecated
public SchemaExport(Configuration cfg, Properties properties) throws HibernateException { public SchemaExport(Configuration configuration, Properties properties) throws HibernateException {
dialect = Dialect.getDialect( properties ); final Dialect dialect = Dialect.getDialect( properties );
Properties props = new Properties(); Properties props = new Properties();
props.putAll( dialect.getDefaultProperties() ); props.putAll( dialect.getDefaultProperties() );
props.putAll( properties ); props.putAll( properties );
this.connectionHelper = new ManagedProviderConnectionHelper( props );
connectionHelper = new ManagedProviderConnectionHelper( props ); this.sqlStatementLogger = new SqlStatementLogger( false, true );
dropSQL = cfg.generateDropSchemaScript( dialect ); this.formatter = FormatStyle.DDL.getFormatter();
createSQL = cfg.generateSchemaCreationScript( dialect ); this.sqlExceptionHelper = new SqlExceptionHelper();
formatter = ( ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, props ) ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter(); this.importFiles = ConfigurationHelper.getString(
Environment.HBM2DDL_IMPORT_FILES,
properties,
DEFAULT_IMPORT_FILE
);
importFiles = ConfigurationHelper.getString( Environment.HBM2DDL_IMPORT_FILES, props, DEFAULT_IMPORT_FILE ); this.dropSQL = configuration.generateDropSchemaScript( dialect );
this.createSQL = configuration.generateSchemaCreationScript( dialect );
} }
/** /**
* Create a schema exporter for the given Configuration, using the supplied connection for connectivity. * Create a schema exporter for the given Configuration, using the supplied connection for connectivity.
* *
* @param cfg The configuration to use. * @param configuration The configuration to use.
* @param connection The JDBC connection to use. * @param connection The JDBC connection to use.
* @throws HibernateException Indicates problem preparing for schema export. * @throws HibernateException Indicates problem preparing for schema export.
*/ */
public SchemaExport(Configuration cfg, Connection connection) throws HibernateException { public SchemaExport(Configuration configuration, Connection connection) throws HibernateException {
this.connectionHelper = new SuppliedConnectionHelper( connection ); this.connectionHelper = new SuppliedConnectionHelper( connection );
dialect = Dialect.getDialect( cfg.getProperties() );
dropSQL = cfg.generateDropSchemaScript( dialect ); this.sqlStatementLogger = new SqlStatementLogger( false, true );
createSQL = cfg.generateSchemaCreationScript( dialect ); this.formatter = FormatStyle.DDL.getFormatter();
formatter = ( ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, cfg.getProperties() ) ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter(); this.sqlExceptionHelper = new SqlExceptionHelper();
importFiles = ConfigurationHelper.getString( Environment.HBM2DDL_IMPORT_FILES, cfg.getProperties(),
this.importFiles = ConfigurationHelper.getString(
Environment.HBM2DDL_IMPORT_FILES,
configuration.getProperties(),
DEFAULT_IMPORT_FILE DEFAULT_IMPORT_FILE
); );
final Dialect dialect = Dialect.getDialect( configuration.getProperties() );
this.dropSQL = configuration.generateDropSchemaScript( dialect );
this.createSQL = configuration.generateSchemaCreationScript( dialect );
} }
public SchemaExport( public SchemaExport(
@ -165,6 +195,8 @@ public class SchemaExport {
this.dropSQL = dropSql; this.dropSQL = dropSql;
this.createSQL = createSql; this.createSQL = createSql;
this.importFiles = ""; this.importFiles = "";
this.sqlStatementLogger = new SqlStatementLogger( false, true );
this.sqlExceptionHelper = new SqlExceptionHelper();
this.formatter = FormatStyle.DDL.getFormatter(); this.formatter = FormatStyle.DDL.getFormatter();
} }
@ -179,19 +211,6 @@ public class SchemaExport {
return this; return this;
} }
/**
* An import file, containing raw SQL statements to be executed.
*
* @param filename The import file name.
* @return this
* @deprecated use {@link org.hibernate.cfg.Environment#HBM2DDL_IMPORT_FILES}
*/
@Deprecated
public SchemaExport setImportFile(String filename) {
importFiles = filename;
return this;
}
/** /**
* Set the end of statement delimiter * Set the end of statement delimiter
* *
@ -232,7 +251,11 @@ public class SchemaExport {
* @param export export the script to the database * @param export export the script to the database
*/ */
public void create(boolean script, boolean export) { public void create(boolean script, boolean export) {
execute( script, export, false, false ); create( Target.interpret( script, export ) );
}
public void create(Target output) {
execute( output, Type.CREATE );
} }
/** /**
@ -242,22 +265,38 @@ public class SchemaExport {
* @param export export the script to the database * @param export export the script to the database
*/ */
public void drop(boolean script, boolean export) { public void drop(boolean script, boolean export) {
execute( script, export, true, false ); drop( Target.interpret( script, export ) );
}
public void drop(Target output) {
execute( output, Type.DROP );
} }
public void execute(boolean script, boolean export, boolean justDrop, boolean justCreate) { public void execute(boolean script, boolean export, boolean justDrop, boolean justCreate) {
execute( Target.interpret( script, export ), interpretType( justDrop, justCreate ) );
}
private Type interpretType(boolean justDrop, boolean justCreate) {
if ( justDrop ) {
return Type.DROP;
}
else if ( justCreate ) {
return Type.CREATE;
}
else {
return Type.BOTH;
}
}
public void execute(Target output, Type type) {
if ( output == Target.NONE || type == SchemaExport.Type.NONE ) {
return;
}
exceptions.clear();
LOG.runningHbm2ddlSchemaExport(); LOG.runningHbm2ddlSchemaExport();
Connection connection = null; final List<NamedReader> importFileReaders = new ArrayList<NamedReader>();
Writer outputFileWriter = null;
List<NamedReader> importFileReaders = new ArrayList<NamedReader>();
Statement statement = null;
exceptions.clear();
try {
for ( String currentFile : importFiles.split(",") ) { for ( String currentFile : importFiles.split(",") ) {
try { try {
final String resourceName = currentFile.trim(); final String resourceName = currentFile.trim();
@ -269,76 +308,111 @@ public class SchemaExport {
} }
} }
final List<Exporter> exporters = new ArrayList<Exporter>();
try {
// prepare exporters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ( output.doScript() ) {
exporters.add( new ScriptExporter() );
}
if ( outputFile != null ) { if ( outputFile != null ) {
LOG.writingGeneratedSchemaToFile(outputFile); exporters.add( new FileExporter( outputFile ) );
outputFileWriter = new FileWriter( outputFile ); }
if ( output.doExport() ) {
exporters.add( new DatabaseExporter( connectionHelper, sqlExceptionHelper ) );
} }
if ( export ) { // perform exporters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LOG.exportingGeneratedSchemaToDatabase(); if ( type.doDrop() ) {
connectionHelper.prepare( true ); perform( dropSQL, exporters );
connection = connectionHelper.getConnection();
statement = connection.createStatement();
} }
if ( type.doCreate() ) {
if ( !justCreate ) { perform( createSQL, exporters );
drop( script, export, outputFileWriter, statement ); if ( ! importFileReaders.isEmpty() ) {
} for ( NamedReader namedReader : importFileReaders ) {
importScript( namedReader, exporters );
if ( !justDrop ) {
create( script, export, outputFileWriter, statement );
if ( export && importFileReaders.size() > 0 ) {
for (NamedReader reader : importFileReaders) {
importScript( reader, statement );
} }
} }
} }
LOG.schemaExportComplete();
} }
catch (Exception e) { catch (Exception e) {
exceptions.add( e ); exceptions.add( e );
LOG.schemaExportUnsuccessful( e ); LOG.schemaExportUnsuccessful( e );
} }
finally { finally {
// release exporters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for ( Exporter exporter : exporters ) {
try { try {
if ( statement != null ) { exporter.release();
statement.close(); }
catch (Exception ignore) {
}
}
// release the named readers from import scripts
for ( NamedReader namedReader : importFileReaders ) {
try {
namedReader.getReader().close();
}
catch (Exception ignore) {
}
}
LOG.schemaExportComplete();
}
}
private void perform(String[] sqlCommands, List<Exporter> exporters) {
for ( String sqlCommand : sqlCommands ) {
String formatted = formatter.format( sqlCommand );
if ( delimiter != null ) {
formatted += delimiter;
}
sqlStatementLogger.logStatement( formatted );
for ( Exporter exporter : exporters ) {
try {
exporter.export( formatted );
}
catch (Exception e) {
if ( haltOnError ) {
throw new HibernateException( "Error during DDL export", e );
}
exceptions.add( e );
LOG.unsuccessfulCreate( sqlCommand );
LOG.error( e.getMessage() );
}
}
}
}
private void importScript(NamedReader namedReader, List<Exporter> exporters) throws Exception {
BufferedReader reader = new BufferedReader( namedReader.getReader() );
long lineNo = 0;
for ( String sql = reader.readLine(); sql != null; sql = reader.readLine() ) {
try {
lineNo++;
String trimmedSql = sql.trim();
if ( trimmedSql.length() == 0 ||
trimmedSql.startsWith( "--" ) ||
trimmedSql.startsWith( "//" ) ||
trimmedSql.startsWith( "/*" ) ) {
continue;
}
if ( trimmedSql.endsWith(";") ) {
trimmedSql = trimmedSql.substring(0, trimmedSql.length() - 1);
}
LOG.debugf( trimmedSql );
for ( Exporter exporter: exporters ) {
if ( exporter.acceptsImportScripts() ) {
exporter.export( trimmedSql );
} }
if ( connection != null ) {
connectionHelper.release();
} }
} }
catch ( Exception e ) { catch ( Exception e ) {
exceptions.add( e ); throw new ImportScriptException( "Error during import script execution at line " + lineNo, e );
LOG.unableToCloseConnection(e);
}
try {
if ( outputFileWriter != null ) {
outputFileWriter.close();
}
}
catch ( IOException ioe ) {
exceptions.add( ioe );
LOG.unableToCloseOutputFile(outputFile, ioe);
}
for (NamedReader reader : importFileReaders) {
try {
reader.getReader().close();
} catch (IOException ioe) {
exceptions.add(ioe);
LOG.unableToCloseInputFiles(reader.getName(), ioe);
}
} }
} }
} }
private class NamedReader { private static class NamedReader {
private final Reader reader; private final Reader reader;
private final String name; private final String name;
@ -356,62 +430,6 @@ public class SchemaExport {
} }
} }
private void importScript(NamedReader importFileReader, Statement statement)
throws IOException {
LOG.executingImportScript(importFileReader.getName());
BufferedReader reader = new BufferedReader( importFileReader.getReader() );
long lineNo = 0;
for ( String sql = reader.readLine(); sql != null; sql = reader.readLine() ) {
try {
lineNo++;
String trimmedSql = sql.trim();
if ( trimmedSql.length() == 0 ||
trimmedSql.startsWith( "--" ) ||
trimmedSql.startsWith( "//" ) ||
trimmedSql.startsWith( "/*" ) ) {
continue;
}
if (trimmedSql.endsWith(";")) trimmedSql = trimmedSql.substring(0, trimmedSql.length() - 1);
LOG.debugf(trimmedSql);
statement.execute(trimmedSql);
}
catch ( SQLException e ) {
throw new JDBCException( "Error during import script execution at line " + lineNo, e );
}
}
}
private void create(boolean script, boolean export, Writer fileOutput, Statement statement)
throws IOException {
for ( int j = 0; j < createSQL.length; j++ ) {
try {
execute( script, export, fileOutput, statement, createSQL[j] );
}
catch ( SQLException e ) {
if ( haltOnError ) {
throw new JDBCException( "Error during DDL export", e );
}
exceptions.add( e );
LOG.unsuccessfulCreate(createSQL[j]);
LOG.error(e.getMessage());
}
}
}
private void drop(boolean script, boolean export, Writer fileOutput, Statement statement)
throws IOException {
for ( int i = 0; i < dropSQL.length; i++ ) {
try {
execute( script, export, fileOutput, statement, dropSQL[i] );
}
catch ( SQLException e ) {
exceptions.add( e );
LOG.debugf("Unsuccessful: %s", dropSQL[i]);
LOG.debugf(e.getMessage());
}
}
}
private void execute(boolean script, boolean export, Writer fileOutput, Statement statement, final String sql) private void execute(boolean script, boolean export, Writer fileOutput, Statement statement, final String sql)
throws IOException, SQLException { throws IOException, SQLException {
final SqlExceptionHelper sqlExceptionHelper = new SqlExceptionHelper(); final SqlExceptionHelper sqlExceptionHelper = new SqlExceptionHelper();
@ -437,7 +455,6 @@ public class SchemaExport {
} }
} }
} }
private static BasicServiceRegistryImpl createServiceRegistry(Properties properties) { private static BasicServiceRegistryImpl createServiceRegistry(Properties properties) {
@ -528,7 +545,7 @@ public class SchemaExport {
BasicServiceRegistryImpl serviceRegistry = createServiceRegistry( cfg.getProperties() ); BasicServiceRegistryImpl serviceRegistry = createServiceRegistry( cfg.getProperties() );
try { try {
SchemaExport se = new SchemaExport( serviceRegistry.getService( JdbcServices.class ), cfg ) SchemaExport se = new SchemaExport( serviceRegistry, cfg )
.setHaltOnError( halt ) .setHaltOnError( halt )
.setOutputFile( outFile ) .setOutputFile( outFile )
.setDelimiter( delim ); .setDelimiter( delim );
@ -555,4 +572,5 @@ public class SchemaExport {
public List getExceptions() { public List getExceptions() {
return exceptions; return exceptions;
} }
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC. * distributed under license by Red Hat Inc.
* *
* This copyrighted material is made available to anyone wishing to use, modify, * This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,7 +20,6 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.tool.hbm2ddl; package org.hibernate.tool.hbm2ddl;
@ -33,6 +32,9 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import org.jboss.logging.Logger;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.HibernateLogger; import org.hibernate.HibernateLogger;
import org.hibernate.JDBCException; import org.hibernate.JDBCException;
@ -43,57 +45,65 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.internal.FormatStyle; import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.hibernate.engine.jdbc.internal.Formatter; import org.hibernate.engine.jdbc.internal.Formatter;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger; import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.internal.BasicServiceRegistryImpl; import org.hibernate.service.internal.BasicServiceRegistryImpl;
import org.jboss.logging.Logger;
/** /**
* A commandline tool to update a database schema. May also be called from * A commandline tool to update a database schema. May also be called from inside an application.
* inside an application.
* *
* @author Christoph Sturm * @author Christoph Sturm
* @author Steve Ebersole
*/ */
public class SchemaUpdate { public class SchemaUpdate {
private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, SchemaUpdate.class.getName()); private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, SchemaUpdate.class.getName());
private ConnectionHelper connectionHelper;
private Configuration configuration; private final Configuration configuration;
private Dialect dialect; private final ConnectionHelper connectionHelper;
private List exceptions; private final SqlStatementLogger sqlStatementLogger;
private final SqlExceptionHelper sqlExceptionHelper;
private final Dialect dialect;
private final List<Exception> exceptions = new ArrayList<Exception>();
private Formatter formatter;
private boolean haltOnError = false; private boolean haltOnError = false;
private boolean format = true; private boolean format = true;
private String outputFile = null; private String outputFile = null;
private String delimiter; private String delimiter;
private Formatter formatter;
private SqlStatementLogger sqlStatementLogger;
public SchemaUpdate(Configuration cfg) throws HibernateException { public SchemaUpdate(Configuration cfg) throws HibernateException {
this( cfg, cfg.getProperties() ); this( cfg, cfg.getProperties() );
} }
public SchemaUpdate(Configuration cfg, Properties connectionProperties) throws HibernateException { public SchemaUpdate(Configuration configuration, Properties properties) throws HibernateException {
this.configuration = cfg; this.configuration = configuration;
dialect = Dialect.getDialect( connectionProperties ); this.dialect = Dialect.getDialect( properties );
Properties props = new Properties(); Properties props = new Properties();
props.putAll( dialect.getDefaultProperties() ); props.putAll( dialect.getDefaultProperties() );
props.putAll( connectionProperties ); props.putAll( properties );
connectionHelper = new ManagedProviderConnectionHelper( props ); this.connectionHelper = new ManagedProviderConnectionHelper( props );
exceptions = new ArrayList();
formatter = ( ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, props ) ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter(); this.sqlExceptionHelper = new SqlExceptionHelper();
this.sqlStatementLogger = new SqlStatementLogger( false, true );
this.formatter = FormatStyle.DDL.getFormatter();
} }
public SchemaUpdate(JdbcServices jdbcServices, Configuration cfg) throws HibernateException { public SchemaUpdate(ServiceRegistry serviceRegistry, Configuration cfg) throws HibernateException {
this.configuration = cfg; this.configuration = cfg;
dialect = jdbcServices.getDialect();
connectionHelper = new SuppliedConnectionProviderConnectionHelper( final JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class );
jdbcServices.getConnectionProvider() this.dialect = jdbcServices.getDialect();
); this.connectionHelper = new SuppliedConnectionProviderConnectionHelper( jdbcServices.getConnectionProvider() );
exceptions = new ArrayList();
sqlStatementLogger = jdbcServices.getSqlStatementLogger(); this.sqlExceptionHelper = new SqlExceptionHelper();
formatter = ( sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter(); this.sqlStatementLogger = jdbcServices.getSqlStatementLogger();
this.formatter = ( sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter();
} }
private static BasicServiceRegistryImpl createServiceRegistry(Properties properties) { private static BasicServiceRegistryImpl createServiceRegistry(Properties properties) {
@ -146,7 +156,7 @@ public class SchemaUpdate {
BasicServiceRegistryImpl serviceRegistry = createServiceRegistry( cfg.getProperties() ); BasicServiceRegistryImpl serviceRegistry = createServiceRegistry( cfg.getProperties() );
try { try {
new SchemaUpdate( serviceRegistry.getService( JdbcServices.class ), cfg ).execute( script, doUpdate ); new SchemaUpdate( serviceRegistry, cfg ).execute( script, doUpdate );
} }
finally { finally {
serviceRegistry.destroy(); serviceRegistry.destroy();
@ -164,7 +174,10 @@ public class SchemaUpdate {
* @param script print all DDL to the console * @param script print all DDL to the console
*/ */
public void execute(boolean script, boolean doUpdate) { public void execute(boolean script, boolean doUpdate) {
execute( Target.interpret( script, doUpdate ) );
}
public void execute(Target target) {
LOG.runningHbm2ddlSchemaUpdate(); LOG.runningHbm2ddlSchemaUpdate();
Connection connection = null; Connection connection = null;
@ -174,7 +187,6 @@ public class SchemaUpdate {
exceptions.clear(); exceptions.clear();
try { try {
DatabaseMetadata meta; DatabaseMetadata meta;
try { try {
LOG.fetchingDatabaseMetadata(); LOG.fetchingDatabaseMetadata();
@ -191,28 +203,25 @@ public class SchemaUpdate {
LOG.updatingSchema(); LOG.updatingSchema();
if ( outputFile != null ) { if ( outputFile != null ) {
LOG.writingGeneratedSchemaToFile( outputFile ); LOG.writingGeneratedSchemaToFile( outputFile );
outputFileWriter = new FileWriter( outputFile ); outputFileWriter = new FileWriter( outputFile );
} }
String[] createSQL = configuration.generateSchemaUpdateScript( dialect, meta ); String[] sqlStrings = configuration.generateSchemaUpdateScript( dialect, meta );
for ( int j = 0; j < createSQL.length; j++ ) { for ( String sql : sqlStrings ) {
final String sql = createSQL[j];
String formatted = formatter.format( sql ); String formatted = formatter.format( sql );
try { try {
if ( delimiter != null ) { if ( delimiter != null ) {
formatted += delimiter; formatted += delimiter;
} }
if ( script ) { if ( target.doScript() ) {
System.out.println( formatted ); System.out.println( formatted );
} }
if ( outputFile != null ) { if ( outputFile != null ) {
outputFileWriter.write( formatted + "\n" ); outputFileWriter.write( formatted + "\n" );
} }
if ( doUpdate ) { if ( target.doExport() ) {
LOG.debugf( sql ); LOG.debugf( sql );
stmt.executeUpdate( formatted ); stmt.executeUpdate( formatted );
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC. * distributed under license by Red Hat Inc.
* *
* This copyrighted material is made available to anyone wishing to use, modify, * This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,7 +20,6 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.tool.hbm2ddl; package org.hibernate.tool.hbm2ddl;
@ -28,6 +27,9 @@ import java.io.FileInputStream;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Properties; import java.util.Properties;
import org.jboss.logging.Logger;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.HibernateLogger; import org.hibernate.HibernateLogger;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
@ -37,10 +39,9 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.internal.BasicServiceRegistryImpl; import org.hibernate.service.internal.BasicServiceRegistryImpl;
import org.jboss.logging.Logger;
/** /**
* A commandline tool to update a database schema. May also be called from * A commandline tool to update a database schema. May also be called from
* inside an application. * inside an application.
@ -48,7 +49,6 @@ import org.jboss.logging.Logger;
* @author Christoph Sturm * @author Christoph Sturm
*/ */
public class SchemaValidator { public class SchemaValidator {
private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, SchemaValidator.class.getName()); private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, SchemaValidator.class.getName());
private ConnectionHelper connectionHelper; private ConnectionHelper connectionHelper;
@ -68,12 +68,11 @@ public class SchemaValidator {
connectionHelper = new ManagedProviderConnectionHelper( props ); connectionHelper = new ManagedProviderConnectionHelper( props );
} }
public SchemaValidator(JdbcServices jdbcServices, Configuration cfg ) throws HibernateException { public SchemaValidator(ServiceRegistry serviceRegistry, Configuration cfg ) throws HibernateException {
this.configuration = cfg; this.configuration = cfg;
dialect = jdbcServices.getDialect(); final JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class );
connectionHelper = new SuppliedConnectionProviderConnectionHelper( this.dialect = jdbcServices.getDialect();
jdbcServices.getConnectionProvider() this.connectionHelper = new SuppliedConnectionProviderConnectionHelper( jdbcServices.getConnectionProvider() );
);
} }
private static BasicServiceRegistryImpl createServiceRegistry(Properties properties) { private static BasicServiceRegistryImpl createServiceRegistry(Properties properties) {
@ -117,7 +116,7 @@ public class SchemaValidator {
BasicServiceRegistryImpl serviceRegistry = createServiceRegistry( cfg.getProperties() ); BasicServiceRegistryImpl serviceRegistry = createServiceRegistry( cfg.getProperties() );
try { try {
new SchemaValidator( serviceRegistry.getService( JdbcServices.class ), cfg ).validate(); new SchemaValidator( serviceRegistry, cfg ).validate();
} }
finally { finally {
serviceRegistry.destroy(); serviceRegistry.destroy();

View File

@ -0,0 +1,43 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program 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 this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.hbm2ddl;
/**
* @author Steve Ebersole
*/
class ScriptExporter implements Exporter {
@Override
public boolean acceptsImportScripts() {
return false;
}
@Override
public void export(String string) throws Exception {
System.out.println( string );
}
@Override
public void release() throws Exception {
}
}

View File

@ -0,0 +1,51 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program 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 this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.hbm2ddl;
/**
* @author Steve Ebersole
*/
public enum Target {
EXPORT,
SCRIPT,
NONE,
BOTH;
public boolean doExport() {
return this == BOTH || this == EXPORT;
}
public boolean doScript() {
return this == BOTH || this == SCRIPT;
}
public static Target interpret(boolean script, boolean export) {
if ( script ) {
return export ? BOTH : SCRIPT;
}
else {
return export ? EXPORT : NONE;
}
}
}

View File

@ -435,7 +435,7 @@ public class EntityTest extends BaseCoreFunctionalTestCase {
} }
private SchemaExport schemaExport() { private SchemaExport schemaExport() {
return new SchemaExport( serviceRegistry().getService( JdbcServices.class ), configuration() ); return new SchemaExport( serviceRegistry(), configuration() );
} }
@After @After

View File

@ -69,7 +69,7 @@ public class MigrationTest extends BaseUnitTestCase {
v1cfg.addResource( resource1 ); v1cfg.addResource( resource1 );
new SchemaExport( v1cfg ).execute( false, true, true, false ); new SchemaExport( v1cfg ).execute( false, true, true, false );
SchemaUpdate v1schemaUpdate = new SchemaUpdate( getJdbcServices(), v1cfg ); SchemaUpdate v1schemaUpdate = new SchemaUpdate( serviceRegistry, v1cfg );
v1schemaUpdate.execute( true, true ); v1schemaUpdate.execute( true, true );
assertEquals( 0, v1schemaUpdate.getExceptions().size() ); assertEquals( 0, v1schemaUpdate.getExceptions().size() );
@ -77,11 +77,11 @@ public class MigrationTest extends BaseUnitTestCase {
Configuration v2cfg = new Configuration(); Configuration v2cfg = new Configuration();
v2cfg.addResource( resource2 ); v2cfg.addResource( resource2 );
SchemaUpdate v2schemaUpdate = new SchemaUpdate( getJdbcServices(), v2cfg ); SchemaUpdate v2schemaUpdate = new SchemaUpdate( serviceRegistry, v2cfg );
v2schemaUpdate.execute( true, true ); v2schemaUpdate.execute( true, true );
assertEquals( 0, v2schemaUpdate.getExceptions().size() ); assertEquals( 0, v2schemaUpdate.getExceptions().size() );
new SchemaExport( getJdbcServices(), v2cfg ).drop( false, true ); new SchemaExport( serviceRegistry, v2cfg ).drop( false, true );
} }