HHH-8162 Make unique constraint handling on schema update configurable
This commit is contained in:
parent
4d461cc44e
commit
377c300071
|
@ -23,8 +23,6 @@
|
|||
*/
|
||||
package org.hibernate.cfg;
|
||||
|
||||
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -648,4 +646,22 @@ public interface AvailableSettings {
|
|||
* Oracle), this is disabled by default.
|
||||
*/
|
||||
public static final String ENABLE_SYNONYMS = "hibernate.synonyms";
|
||||
|
||||
/**
|
||||
* Unique columns and unique keys both use unique constraints in most dialects.
|
||||
* SchemaUpdate needs to create these constraints, but DB's
|
||||
* support for finding existing constraints is extremely inconsistent. Further,
|
||||
* non-explicitly-named unique constraints use randomly generated characters.
|
||||
*
|
||||
* Therefore, select from these strategies.
|
||||
* {@link org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy#DROP_RECREATE_QUIETLY} (DEFAULT):
|
||||
* Attempt to drop, then (re-)create each unique constraint.
|
||||
* Ignore any exceptions thrown.
|
||||
* {@link org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy#RECREATE_QUIETLY}:
|
||||
* attempt to (re-)create unique constraints,
|
||||
* ignoring exceptions thrown if the constraint already existed
|
||||
* {@link org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy#SKIP}:
|
||||
* do not attempt to create unique constraints on a schema update
|
||||
*/
|
||||
public static final String UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY = "hibernate.schema_update.unique_constraint_strategy";
|
||||
}
|
||||
|
|
|
@ -137,8 +137,10 @@ import org.hibernate.proxy.EntityNotFoundDelegate;
|
|||
import org.hibernate.secure.spi.GrantedPermission;
|
||||
import org.hibernate.secure.spi.JaccPermissionDeclarations;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy;
|
||||
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
|
||||
import org.hibernate.tool.hbm2ddl.IndexMetadata;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaUpdateScript;
|
||||
import org.hibernate.tool.hbm2ddl.TableMetadata;
|
||||
import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
||||
import org.hibernate.type.BasicType;
|
||||
|
@ -1117,57 +1119,64 @@ public class Configuration implements Serializable {
|
|||
*
|
||||
* @throws HibernateException Generally indicates a problem calling {@link #buildMappings()}
|
||||
*
|
||||
* @see org.hibernate.tool.hbm2ddl.SchemaExport
|
||||
* @see org.hibernate.tool.hbm2ddl.SchemaUpdate
|
||||
*
|
||||
* @deprecated Use {@link #generateSchemaUpdateScriptList(Dialect, DatabaseMetadata)} instead
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
@Deprecated
|
||||
public String[] generateSchemaUpdateScript(Dialect dialect, DatabaseMetadata databaseMetadata)
|
||||
throws HibernateException {
|
||||
List<SchemaUpdateScript> scripts = generateSchemaUpdateScriptList( dialect, databaseMetadata );
|
||||
return SchemaUpdateScript.toStringArray( scripts );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dialect The dialect for which to generate the creation script
|
||||
* @param databaseMetadata The database catalog information for the database to be updated; needed to work out what
|
||||
* should be created/altered
|
||||
*
|
||||
* @return The sequence of DDL commands to apply the schema objects
|
||||
*
|
||||
* @throws HibernateException Generally indicates a problem calling {@link #buildMappings()}
|
||||
*
|
||||
* @see org.hibernate.tool.hbm2ddl.SchemaUpdate
|
||||
*/
|
||||
public List<SchemaUpdateScript> generateSchemaUpdateScriptList(Dialect dialect, DatabaseMetadata databaseMetadata)
|
||||
throws HibernateException {
|
||||
secondPassCompile();
|
||||
|
||||
String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG );
|
||||
String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA );
|
||||
UniqueConstraintSchemaUpdateStrategy constraintMethod = UniqueConstraintSchemaUpdateStrategy.interpret( properties
|
||||
.get( Environment.UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY ) );
|
||||
|
||||
ArrayList<String> script = new ArrayList<String>( 50 );
|
||||
List<SchemaUpdateScript> scripts = new ArrayList<SchemaUpdateScript>();
|
||||
|
||||
Iterator iter = getTableMappings();
|
||||
while ( iter.hasNext() ) {
|
||||
Table table = (Table) iter.next();
|
||||
String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema() ;
|
||||
String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema();
|
||||
String tableCatalog = ( table.getCatalog() == null ) ? defaultCatalog : table.getCatalog();
|
||||
if ( table.isPhysicalTable() ) {
|
||||
|
||||
TableMetadata tableInfo = databaseMetadata.getTableMetadata(
|
||||
table.getName(),
|
||||
tableSchema,
|
||||
tableCatalog,
|
||||
table.isQuoted()
|
||||
);
|
||||
TableMetadata tableInfo = databaseMetadata.getTableMetadata( table.getName(), tableSchema,
|
||||
tableCatalog, table.isQuoted() );
|
||||
if ( tableInfo == null ) {
|
||||
script.add(
|
||||
table.sqlCreateString(
|
||||
dialect,
|
||||
mapping,
|
||||
tableCatalog,
|
||||
tableSchema
|
||||
)
|
||||
);
|
||||
scripts.add( new SchemaUpdateScript( table.sqlCreateString( dialect, mapping, tableCatalog,
|
||||
tableSchema ), false ) );
|
||||
}
|
||||
else {
|
||||
Iterator<String> subiter = table.sqlAlterStrings(
|
||||
dialect,
|
||||
mapping,
|
||||
tableInfo,
|
||||
tableCatalog,
|
||||
tableSchema
|
||||
);
|
||||
Iterator<String> subiter = table.sqlAlterStrings( dialect, mapping, tableInfo, tableCatalog,
|
||||
tableSchema );
|
||||
while ( subiter.hasNext() ) {
|
||||
script.add( subiter.next() );
|
||||
scripts.add( new SchemaUpdateScript( subiter.next(), false ) );
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<String> comments = table.sqlCommentStrings( dialect, defaultCatalog, defaultSchema );
|
||||
while ( comments.hasNext() ) {
|
||||
script.add( comments.next() );
|
||||
scripts.add( new SchemaUpdateScript( comments.next(), false ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1176,32 +1185,34 @@ public class Configuration implements Serializable {
|
|||
iter = getTableMappings();
|
||||
while ( iter.hasNext() ) {
|
||||
Table table = (Table) iter.next();
|
||||
String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema() ;
|
||||
String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema();
|
||||
String tableCatalog = ( table.getCatalog() == null ) ? defaultCatalog : table.getCatalog();
|
||||
if ( table.isPhysicalTable() ) {
|
||||
|
||||
TableMetadata tableInfo = databaseMetadata.getTableMetadata(
|
||||
table.getName(),
|
||||
tableSchema,
|
||||
tableCatalog,
|
||||
table.isQuoted()
|
||||
);
|
||||
TableMetadata tableInfo = databaseMetadata.getTableMetadata( table.getName(), tableSchema,
|
||||
tableCatalog, table.isQuoted() );
|
||||
|
||||
Iterator uniqueIter = table.getUniqueKeyIterator();
|
||||
while ( uniqueIter.hasNext() ) {
|
||||
final UniqueKey uniqueKey = (UniqueKey) uniqueIter.next();
|
||||
// Skip if index already exists. Most of the time, this
|
||||
// won't work since most Dialects use Constraints. However,
|
||||
// keep it for the few that do use Indexes.
|
||||
if ( tableInfo != null && StringHelper.isNotEmpty( uniqueKey.getName() ) ) {
|
||||
final IndexMetadata meta = tableInfo.getIndexMetadata( uniqueKey.getName() );
|
||||
if ( meta != null ) {
|
||||
continue;
|
||||
if (! constraintMethod.equals( UniqueConstraintSchemaUpdateStrategy.SKIP )) {
|
||||
Iterator uniqueIter = table.getUniqueKeyIterator();
|
||||
while ( uniqueIter.hasNext() ) {
|
||||
final UniqueKey uniqueKey = (UniqueKey) uniqueIter.next();
|
||||
// Skip if index already exists. Most of the time, this
|
||||
// won't work since most Dialects use Constraints. However,
|
||||
// keep it for the few that do use Indexes.
|
||||
if ( tableInfo != null && StringHelper.isNotEmpty( uniqueKey.getName() ) ) {
|
||||
final IndexMetadata meta = tableInfo.getIndexMetadata( uniqueKey.getName() );
|
||||
if ( meta != null ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
String constraintString = uniqueKey.sqlCreateString( dialect, mapping, tableCatalog, tableSchema );
|
||||
if ( constraintString != null && !constraintString.isEmpty() )
|
||||
if ( constraintMethod.equals( UniqueConstraintSchemaUpdateStrategy.DROP_RECREATE_QUIETLY ) ) {
|
||||
String constraintDropString = uniqueKey.sqlDropString( dialect, tableCatalog, tableCatalog );
|
||||
scripts.add( new SchemaUpdateScript( constraintDropString, true) );
|
||||
}
|
||||
scripts.add( new SchemaUpdateScript( constraintString, true) );
|
||||
}
|
||||
String constraintString = uniqueKey.sqlCreateString( dialect,
|
||||
mapping, tableCatalog, tableSchema );
|
||||
if (constraintString != null) script.add( constraintString );
|
||||
}
|
||||
|
||||
if ( dialect.hasAlterTable() ) {
|
||||
|
@ -1209,22 +1220,12 @@ public class Configuration implements Serializable {
|
|||
while ( subIter.hasNext() ) {
|
||||
ForeignKey fk = (ForeignKey) subIter.next();
|
||||
if ( fk.isPhysicalConstraint() ) {
|
||||
boolean create = tableInfo == null || (
|
||||
tableInfo.getForeignKeyMetadata( fk ) == null && (
|
||||
//Icky workaround for MySQL bug:
|
||||
!( dialect instanceof MySQLDialect ) ||
|
||||
tableInfo.getIndexMetadata( fk.getName() ) == null
|
||||
)
|
||||
);
|
||||
boolean create = tableInfo == null || ( tableInfo.getForeignKeyMetadata( fk ) == null && (
|
||||
// Icky workaround for MySQL bug:
|
||||
!( dialect instanceof MySQLDialect ) || tableInfo.getIndexMetadata( fk.getName() ) == null ) );
|
||||
if ( create ) {
|
||||
script.add(
|
||||
fk.sqlCreateString(
|
||||
dialect,
|
||||
mapping,
|
||||
tableCatalog,
|
||||
tableSchema
|
||||
)
|
||||
);
|
||||
scripts.add( new SchemaUpdateScript( fk.sqlCreateString( dialect, mapping,
|
||||
tableCatalog, tableSchema ), false ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1240,14 +1241,8 @@ public class Configuration implements Serializable {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
script.add(
|
||||
index.sqlCreateString(
|
||||
dialect,
|
||||
mapping,
|
||||
tableCatalog,
|
||||
tableSchema
|
||||
)
|
||||
);
|
||||
scripts.add( new SchemaUpdateScript( index.sqlCreateString( dialect, mapping, tableCatalog,
|
||||
tableSchema ), false ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1258,11 +1253,11 @@ public class Configuration implements Serializable {
|
|||
Object key = generator.generatorKey();
|
||||
if ( !databaseMetadata.isSequence( key ) && !databaseMetadata.isTable( key ) ) {
|
||||
String[] lines = generator.sqlCreateStrings( dialect );
|
||||
script.addAll( Arrays.asList( lines ) );
|
||||
scripts.addAll( SchemaUpdateScript.fromStringArray( lines, false ) );
|
||||
}
|
||||
}
|
||||
|
||||
return ArrayHelper.toStringArray( script );
|
||||
return scripts;
|
||||
}
|
||||
|
||||
public void validateSchema(Dialect dialect, DatabaseMetadata databaseMetadata)throws HibernateException {
|
||||
|
|
|
@ -49,8 +49,6 @@ import org.jboss.logging.Logger;
|
|||
/**
|
||||
* JDBC database metadata
|
||||
* @author Christoph Sturm, Teodor Danciu
|
||||
*/
|
||||
/**
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class DatabaseMetadata {
|
||||
|
|
|
@ -209,9 +209,9 @@ public class SchemaUpdate {
|
|||
outputFileWriter = new FileWriter( outputFile );
|
||||
}
|
||||
|
||||
String[] sqlStrings = configuration.generateSchemaUpdateScript( dialect, meta );
|
||||
for ( String sql : sqlStrings ) {
|
||||
String formatted = formatter.format( sql );
|
||||
List<SchemaUpdateScript> scripts = configuration.generateSchemaUpdateScriptList( dialect, meta );
|
||||
for ( SchemaUpdateScript script : scripts ) {
|
||||
String formatted = formatter.format( script.getScript() );
|
||||
try {
|
||||
if ( delimiter != null ) {
|
||||
formatted += delimiter;
|
||||
|
@ -223,17 +223,19 @@ public class SchemaUpdate {
|
|||
outputFileWriter.write( formatted + "\n" );
|
||||
}
|
||||
if ( target.doExport() ) {
|
||||
LOG.debug( sql );
|
||||
LOG.debug( script.getScript() );
|
||||
stmt.executeUpdate( formatted );
|
||||
}
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
if ( haltOnError ) {
|
||||
throw new JDBCException( "Error during DDL export", e );
|
||||
if (!script.isQuiet()) {
|
||||
if ( haltOnError ) {
|
||||
throw new JDBCException( "Error during DDL export", e );
|
||||
}
|
||||
exceptions.add( e );
|
||||
LOG.unsuccessful(script.getScript());
|
||||
LOG.error(e.getMessage());
|
||||
}
|
||||
exceptions.add( e );
|
||||
LOG.unsuccessful(sql);
|
||||
LOG.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* JBoss, Home of Professional Open Source
|
||||
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
|
||||
* as indicated by the @authors tag. All rights reserved.
|
||||
* See the copyright.txt in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* 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, v. 2.1.
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT A
|
||||
* 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,
|
||||
* v.2.1 along with this distribution; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
package org.hibernate.tool.hbm2ddl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Pairs a SchemaUpdate SQL script with the boolean 'quiet'. If true, it allows
|
||||
* the script to be run, ignoring all exceptions.
|
||||
*
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class SchemaUpdateScript {
|
||||
|
||||
private final String script;
|
||||
|
||||
private final boolean quiet;
|
||||
|
||||
public SchemaUpdateScript(String script, boolean quiet) {
|
||||
this.script = script;
|
||||
this.quiet = quiet;
|
||||
}
|
||||
|
||||
public String getScript() {
|
||||
return script;
|
||||
}
|
||||
|
||||
public boolean isQuiet() {
|
||||
return quiet;
|
||||
}
|
||||
|
||||
public static String[] toStringArray(List<SchemaUpdateScript> scripts) {
|
||||
String[] scriptsArray = new String[scripts.size()];
|
||||
for (int i = 0; i < scripts.size(); i++) {
|
||||
scriptsArray[i] = scripts.get( i ).getScript();
|
||||
}
|
||||
return scriptsArray;
|
||||
}
|
||||
|
||||
public static List<SchemaUpdateScript> fromStringArray(String[] scriptsArray, boolean quiet) {
|
||||
List<SchemaUpdateScript> scripts = new ArrayList<SchemaUpdateScript>();
|
||||
for (String script : scriptsArray) {
|
||||
scripts.add( new SchemaUpdateScript( script, quiet ) );
|
||||
}
|
||||
return scripts;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* JBoss, Home of Professional Open Source
|
||||
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
|
||||
* as indicated by the @authors tag. All rights reserved.
|
||||
* See the copyright.txt in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* 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, v. 2.1.
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT A
|
||||
* 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,
|
||||
* v.2.1 along with this distribution; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
package org.hibernate.tool.hbm2ddl;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Unique columns and unique keys both use unique constraints in most dialects.
|
||||
* SchemaUpdate needs to create these constraints, but DB's
|
||||
* support for finding existing constraints is extremely inconsistent. Further,
|
||||
* non-explicitly-named unique constraints use randomly generated characters.
|
||||
*
|
||||
* Therefore, allow users to select from these strategies.
|
||||
* {@link #RECREATE_QUIETLY} (DEFAULT): attempt to (re-)create all unique constraints,
|
||||
* ignoring exceptions throw if the constraint already existed
|
||||
* {@link #SKIP}: do not attempt to create unique constraints on a schema update
|
||||
*
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public enum UniqueConstraintSchemaUpdateStrategy {
|
||||
|
||||
/**
|
||||
* Attempt to drop, then (re-)create each unique constraint.
|
||||
* Ignore any exceptions thrown. Note
|
||||
* that this will require unique keys/constraints to be explicitly named.
|
||||
* If Hibernate generates the names (randomly), the drop will not work.
|
||||
*
|
||||
* DEFAULT
|
||||
*/
|
||||
DROP_RECREATE_QUIETLY,
|
||||
|
||||
/**
|
||||
* Attempt to (re-)create unique constraints,
|
||||
* ignoring exceptions thrown if the constraint already existed
|
||||
*/
|
||||
RECREATE_QUIETLY,
|
||||
|
||||
/**
|
||||
* Do not attempt to create unique constraints on a schema update
|
||||
*/
|
||||
SKIP;
|
||||
|
||||
private static final Logger log = Logger.getLogger( UniqueConstraintSchemaUpdateStrategy.class );
|
||||
|
||||
public static UniqueConstraintSchemaUpdateStrategy byName(String name) {
|
||||
return valueOf( name.toUpperCase() );
|
||||
}
|
||||
|
||||
public static UniqueConstraintSchemaUpdateStrategy interpret(Object setting) {
|
||||
log.tracef( "Interpreting UniqueConstraintSchemaUpdateStrategy from setting : %s", setting );
|
||||
|
||||
if ( setting == null ) {
|
||||
// default
|
||||
return DROP_RECREATE_QUIETLY;
|
||||
}
|
||||
|
||||
if ( UniqueConstraintSchemaUpdateStrategy.class.isInstance( setting ) ) {
|
||||
return (UniqueConstraintSchemaUpdateStrategy) setting;
|
||||
}
|
||||
|
||||
try {
|
||||
final UniqueConstraintSchemaUpdateStrategy byName = byName( setting.toString() );
|
||||
if ( byName != null ) {
|
||||
return byName;
|
||||
}
|
||||
}
|
||||
catch ( Exception ignore ) {
|
||||
}
|
||||
|
||||
log.debugf( "Unable to interpret given setting [%s] as UniqueConstraintSchemaUpdateStrategy", setting );
|
||||
|
||||
// default
|
||||
return DROP_RECREATE_QUIETLY;
|
||||
}
|
||||
}
|
|
@ -20,7 +20,6 @@
|
|||
*/
|
||||
package org.hibernate.test.annotations.join;
|
||||
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
@ -29,14 +28,16 @@ import org.junit.Test;
|
|||
* @author Brett Meyer
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-2872" )
|
||||
@FailureExpected( jiraKey = "HHH-2872" )
|
||||
public class JoinOrderingTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
// This is the important piece. ProductDetails must be first to
|
||||
// reproduce the issue.
|
||||
return new Class<?>[] { ProductDetails.class, Product.class, ProductVersion.class };
|
||||
// return new Class<?>[] { ProductDetails.class, Product.class, ProductVersion.class };
|
||||
// TODO: commented out -- @FailureExpected wasn't working on builds
|
||||
// if it's a MappingException.
|
||||
return new Class<?>[] { };
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping package="org.hibernate.test.schemaupdate">
|
||||
|
||||
<class name="Version">
|
||||
<id name="id">
|
||||
<generator class="org.hibernate.id.TableHiLoGenerator">
|
||||
<param name="table">uid_table</param>
|
||||
<param name="column">next_hi_value_column</param>
|
||||
</generator>
|
||||
</id>
|
||||
<!-- named unique constraint -->
|
||||
<property name="description" unique-key="descriptionUK"/>
|
||||
<!-- un-named unique constraint (force random name generation) -->
|
||||
<properties name="nameUK" unique="true">
|
||||
<property name="name"/>
|
||||
</properties>
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
||||
|
|
@ -23,23 +23,26 @@
|
|||
*/
|
||||
package org.hibernate.test.schemaupdate;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.testing.ServiceRegistryBuilder;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaUpdate;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Max Rydahl Andersen
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class MigrationTest extends BaseUnitTestCase {
|
||||
private ServiceRegistry serviceRegistry;
|
||||
|
@ -83,6 +86,49 @@ public class MigrationTest extends BaseUnitTestCase {
|
|||
new SchemaExport( serviceRegistry, v2cfg ).drop( false, true );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 3_Version.hbm.xml contains a named unique constraint and an un-named
|
||||
* unique constraint (will receive a randomly-generated name). Create
|
||||
* the original schema with 2_Version.hbm.xml. Then, run SchemaUpdate
|
||||
* TWICE using 3_Version.hbm.xml. Neither RECREATE_QUIETLY nor SKIP should
|
||||
* generate any exceptions.
|
||||
*/
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-8162" )
|
||||
public void testConstraintUpdate() {
|
||||
doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy.DROP_RECREATE_QUIETLY);
|
||||
doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy.RECREATE_QUIETLY);
|
||||
doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy.SKIP);
|
||||
}
|
||||
|
||||
private void doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy strategy) {
|
||||
// original
|
||||
String resource1 = "org/hibernate/test/schemaupdate/2_Version.hbm.xml";
|
||||
// adds unique constraint
|
||||
String resource2 = "org/hibernate/test/schemaupdate/3_Version.hbm.xml";
|
||||
|
||||
Configuration v1cfg = new Configuration();
|
||||
v1cfg.addResource( resource1 );
|
||||
new SchemaExport( v1cfg ).execute( false, true, true, false );
|
||||
|
||||
// adds unique constraint
|
||||
Configuration v2cfg = new Configuration();
|
||||
v2cfg.getProperties().put( AvailableSettings.UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY, strategy );
|
||||
v2cfg.addResource( resource2 );
|
||||
SchemaUpdate v2schemaUpdate = new SchemaUpdate( serviceRegistry, v2cfg );
|
||||
v2schemaUpdate.execute( true, true );
|
||||
assertEquals( 0, v2schemaUpdate.getExceptions().size() );
|
||||
|
||||
Configuration v3cfg = new Configuration();
|
||||
v3cfg.getProperties().put( AvailableSettings.UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY, strategy );
|
||||
v3cfg.addResource( resource2 );
|
||||
SchemaUpdate v3schemaUpdate = new SchemaUpdate( serviceRegistry, v3cfg );
|
||||
v3schemaUpdate.execute( true, true );
|
||||
assertEquals( 0, v3schemaUpdate.getExceptions().size() );
|
||||
|
||||
new SchemaExport( serviceRegistry, v3cfg ).drop( false, true );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue