From ba59bbf11941bf632b59db9de9e854e3b840fcf0 Mon Sep 17 00:00:00 2001 From: Brett Meyer Date: Wed, 31 Jul 2013 08:59:43 -0400 Subject: [PATCH] HHH-8224 unique key, foreign key, and index naming strategies --- .../hibernate/cfg/DefaultNamingStrategy.java | 19 +++ .../org/hibernate/cfg/EJB3NamingStrategy.java | 19 +++ .../hibernate/cfg/ImprovedNamingStrategy.java | 19 +++ .../org/hibernate/cfg/NamingStrategy.java | 30 +++++ .../util/collections/CollectionHelper.java | 6 + .../hibernate/metamodel/internal/Binder.java | 61 +++------- .../ConstraintNamingStrategyHelper.java | 109 ++++++++++++++++++ .../metamodel/internal/ForeignKeyHelper.java | 54 +-------- .../metamodel/internal/HashedNameUtil.java | 24 ++-- .../internal/NaturalIdUniqueKeyHelper.java | 7 ++ .../metamodel/internal/TableHelper.java | 45 +++++++- .../annotations/global/TableProcessor.java | 47 +------- .../metamodel/spi/relational/ForeignKey.java | 48 -------- .../metamodel/spi/relational/InLineView.java | 2 +- .../metamodel/spi/relational/Index.java | 4 + .../metamodel/spi/relational/Table.java | 12 +- .../spi/relational/TableSpecification.java | 2 +- 17 files changed, 287 insertions(+), 221 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/ConstraintNamingStrategyHelper.java diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java index a3922b0c56..1dd425a3a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java @@ -24,9 +24,12 @@ package org.hibernate.cfg; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.HashedNameUtil; /** * The default NamingStrategy @@ -93,6 +96,22 @@ public class DefaultNamingStrategy implements NamingStrategy, Serializable { if (header == null) throw new AssertionFailure("NammingStrategy not properly filled"); return columnName( header ); //+ "_" + referencedColumnName not used for backward compatibility } + + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames) { + List combinedColumnNames = new ArrayList(); + combinedColumnNames.addAll( sourceColumnNames ); + combinedColumnNames.addAll( targetColumnNames ); + return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames ); + } + + public String uniqueKeyName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "UK_", tableName, columnNames ); + } + + public String indexName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "IDX_", tableName, columnNames ); + } /** * Return the column name or the unqualified property name diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java index 25d1c2bce2..31068fb37a 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java @@ -23,9 +23,12 @@ */ package org.hibernate.cfg; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.HashedNameUtil; /** * Naming strategy implementing the EJB3 standards @@ -76,6 +79,22 @@ public class EJB3NamingStrategy implements NamingStrategy, Serializable { if ( header == null ) throw new AssertionFailure( "NamingStrategy not properly filled" ); return columnName( header + "_" + referencedColumnName ); } + + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames) { + List combinedColumnNames = new ArrayList(); + combinedColumnNames.addAll( sourceColumnNames ); + combinedColumnNames.addAll( targetColumnNames ); + return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames ); + } + + public String uniqueKeyName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "UK_", tableName, columnNames ); + } + + public String indexName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "IDX_", tableName, columnNames ); + } public String logicalColumnName(String columnName, String propertyName) { return StringHelper.isNotEmpty( columnName ) ? columnName : StringHelper.unqualify( propertyName ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java index b9be3483c7..f794d64bd9 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java @@ -24,9 +24,12 @@ package org.hibernate.cfg; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.HashedNameUtil; /** * An improved naming strategy that prefers embedded @@ -106,6 +109,22 @@ public class ImprovedNamingStrategy implements NamingStrategy, Serializable { if (header == null) throw new AssertionFailure("NamingStrategy not properly filled"); return columnName( header ); //+ "_" + referencedColumnName not used for backward compatibility } + + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames) { + List combinedColumnNames = new ArrayList(); + combinedColumnNames.addAll( sourceColumnNames ); + combinedColumnNames.addAll( targetColumnNames ); + return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames ); + } + + public String uniqueKeyName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "UK_", tableName, columnNames ); + } + + public String indexName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "IDX_", tableName, columnNames ); + } /** * Return the column name or the unqualified property name diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java index c78e0f2f03..e4be023d9b 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java @@ -23,6 +23,8 @@ */ package org.hibernate.cfg; +import java.util.List; + /** * A set of rules for determining the physical column @@ -37,6 +39,7 @@ package org.hibernate.cfg; * @see ImprovedNamingStrategy * @author Gavin King * @author Emmanuel Bernard + * @author Brett Meyer */ public interface NamingStrategy { /** @@ -93,6 +96,33 @@ public interface NamingStrategy { public String foreignKeyColumnName( String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName ); + /** + * Return a constraint name for foreign keys that are not explicitly named in the mappings/annotations. + * + * @param tableName The foreign key's source table + * @param columnNames The source columns within the foreign key + * @param tableName The foreign key's target table + * @param columnNames The target columns within the foreign key + * @return The generated foreign key constraint name + */ + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames); + /** + * Return a constraint name for unique keys that are not explicitly named in the mappings/annotations. + * + * @param tableName The unique key's table + * @param columnNames The columns within the unique key + * @return The generated unique key constraint name + */ + public String uniqueKeyName(String tableName, List columnNames); + /** + * Return a constraint name for indexes that are not explicitly named in the mappings/annotations. + * + * @param tableName The index's table + * @param columnNames The columns within the index + * @return The generated index constraint name + */ + public String indexName(String tableName, List columnNames); /** * Return the logical column name used to refer to a column in the metadata * (like index, unique constraints etc) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java index cefa3d080b..fc46d09e53 100755 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java @@ -207,4 +207,10 @@ public final class CollectionHelper { } } } + + public static List singleEntryList(T entry) { + final List list = new ArrayList(); + list.add( entry ); + return list; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java index 60637efa6e..7baf301d75 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java @@ -112,11 +112,9 @@ import org.hibernate.metamodel.spi.domain.SingularAttribute; import org.hibernate.metamodel.spi.relational.Column; import org.hibernate.metamodel.spi.relational.ForeignKey; import org.hibernate.metamodel.spi.relational.Identifier; -import org.hibernate.metamodel.spi.relational.Index; import org.hibernate.metamodel.spi.relational.PrimaryKey; import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.metamodel.spi.relational.TableSpecification; -import org.hibernate.metamodel.spi.relational.UniqueKey; import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.AggregatedCompositeIdentifierSource; import org.hibernate.metamodel.spi.source.AttributeSource; @@ -222,7 +220,7 @@ public class Binder implements HelperContext { this.tableHelper = new TableHelper( this ); this.foreignKeyHelper = new ForeignKeyHelper( this ); this.relationalValueBindingHelper = new RelationalValueBindingHelper( this ); - this.naturalIdUniqueKeyHelper = new NaturalIdUniqueKeyHelper(); + this.naturalIdUniqueKeyHelper = new NaturalIdUniqueKeyHelper( this ); this.standardAssociationRelationalBindingResolver = new StandardAssociationRelationalBindingResolverImpl( this ); this.mappedByAssociationRelationalBindingResolver = @@ -1127,49 +1125,28 @@ public class Binder implements HelperContext { final EntitySource entitySource = bindingContextContext.getEntitySource(); for ( final ConstraintSource constraintSource : entitySource.getConstraints() ) { if ( UniqueConstraintSource.class.isInstance( constraintSource ) ) { - UniqueConstraintSource uniqueConstraintSource = (UniqueConstraintSource) constraintSource; + final UniqueConstraintSource uniqueConstraintSource = (UniqueConstraintSource) constraintSource; - UniqueKey uk = new UniqueKey(); + final TableSpecification table = findConstraintTable( entityBinding, constraintSource.getTableName() ); - TableSpecification table = findConstraintTable( entityBinding, constraintSource.getTableName() ); - - final List columnNames = uniqueConstraintSource.columnNames(); - final String constraintName = StringHelper.isEmpty( constraintSource.name() ) - ? HashedNameUtil.generateName( "UK_", table, columnNames.toArray( new String[columnNames.size()] ) ) - : constraintSource.name(); - for ( final String columnName : columnNames ) { - uk.addColumn( - tableHelper.locateOrCreateColumn( - table, - columnName, - new ColumnNamingStrategyHelper( null, false ) - - ) - ); + final List columns = new ArrayList(); + for ( final String columnName : uniqueConstraintSource.columnNames() ) { + columns.add( tableHelper.locateOrCreateColumn( table, columnName, + new ColumnNamingStrategyHelper( null, false ) ) ); } - uk.setTable( table ); - uk.setName( constraintName ); - table.addUniqueKey( uk ); + tableHelper.createUniqueKey( table, columns, constraintSource.name() ); } else if ( IndexConstraintSource.class.isInstance( constraintSource ) ) { - IndexConstraintSource indexConstraintSource = (IndexConstraintSource) constraintSource; + final IndexConstraintSource indexConstraintSource = (IndexConstraintSource) constraintSource; - TableSpecification table = findConstraintTable( entityBinding, constraintSource.getTableName() ); + final TableSpecification table = findConstraintTable( entityBinding, constraintSource.getTableName() ); - final List columnNames = indexConstraintSource.columnNames(); - final List orderings = indexConstraintSource.orderings(); - final String constraintName = StringHelper.isEmpty( constraintSource.name() ) - ? HashedNameUtil.generateName( "IDX_", table, columnNames.toArray( new String[columnNames.size()] ) ) - : constraintSource.name(); - final Index index = table.getOrCreateIndex( constraintName ); - for ( int i = 0; i < columnNames.size(); i++ ) { - Column column = tableHelper.locateOrCreateColumn( - table, - columnNames.get( i ), - new DefaultColumnNamingStrategyHelper( null ) - ); - index.addColumn( column, orderings.get( i ) ); + final List columns = new ArrayList(); + for ( final String columnName : indexConstraintSource.columnNames() ) { + columns.add( tableHelper.locateOrCreateColumn( table, columnName, + new ColumnNamingStrategyHelper( null, false ) ) ); } + tableHelper.createIndex( table, columns, constraintSource.name() ); } } } @@ -2477,15 +2454,13 @@ public class Binder implements HelperContext { foreignKey = null; } if ( elementSource.isUnique() ) { - UniqueKey uk = new UniqueKey(); + final List columns = new ArrayList(); for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { if ( ! relationalValueBinding.isDerived() ) { - uk.addColumn( (Column) relationalValueBinding.getValue() ); + columns.add( (Column) relationalValueBinding.getValue() ); } } - uk.setTable( collectionTable ); - HashedNameUtil.setName("UK_", uk); - collectionTable.addUniqueKey( uk ); + tableHelper.createUniqueKey( collectionTable, columns, null ); } elementBinding.setJoinRelationalValueBindings( relationalValueBindings, foreignKey ); typeHelper.bindManyToManyAttributeType( diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ConstraintNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ConstraintNamingStrategyHelper.java new file mode 100644 index 0000000000..9683d7731d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ConstraintNamingStrategyHelper.java @@ -0,0 +1,109 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.metamodel.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * @author Brett Meyer + */ +public abstract class ConstraintNamingStrategyHelper implements ObjectNameNormalizer.NamingStrategyHelper { + + protected final TableSpecification table; + + protected final List columns; + + public ConstraintNamingStrategyHelper(TableSpecification table, List columns) { + this.table = table; + this.columns = columns; + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + return doDetermineImplicitName( strategy, table.getLogicalName().getText(), getColumnNames( columns ) ); + } + + protected abstract String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames); + + @Override + public String handleExplicitName(NamingStrategy strategy, String name) { + return name; + } + + public static class UniqueKeyNamingStrategyHelper extends ConstraintNamingStrategyHelper { + public UniqueKeyNamingStrategyHelper(TableSpecification table, List columns) { + super( table, columns ); + } + + @Override + protected String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames) { + return strategy.uniqueKeyName( tableName, columnNames ); + } + } + + public static class ForeignKeyNamingStrategyHelper extends ConstraintNamingStrategyHelper { + // named using a combo of source/target table/columns + private final String targetTableName; + private final List targetColumnNames; + + public ForeignKeyNamingStrategyHelper(TableSpecification sourceTable, List sourceColumns, + TableSpecification targetTable, List targetColumns) { + super( sourceTable, sourceColumns ); + targetTableName = targetTable.getLogicalName().getText(); + targetColumnNames = getColumnNames( targetColumns ); + } + + @Override + protected String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames) { + // combine source and target (if available) to ensure uniqueness + return strategy.foreignKeyName( tableName, columnNames, targetTableName, targetColumnNames ); + } + } + + public static class IndexNamingStrategyHelper extends ConstraintNamingStrategyHelper { + public IndexNamingStrategyHelper(TableSpecification table, List columns) { + super( table, columns ); + } + + @Override + protected String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames) { + return strategy.indexName( tableName, columnNames ); + } + } + + private static List getColumnNames(List columns) { + final List columnNames = new ArrayList(); + for ( final Column column : columns ) { + columnNames.add( column.getColumnName().getText() ); + } + return columnNames; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ForeignKeyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ForeignKeyHelper.java index 9b79a73632..d21e001fbe 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ForeignKeyHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ForeignKeyHelper.java @@ -27,9 +27,9 @@ import java.util.ArrayList; import java.util.List; import org.hibernate.AssertionFailure; -import org.hibernate.annotations.common.util.StringHelper; import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.metamodel.internal.ConstraintNamingStrategyHelper.ForeignKeyNamingStrategyHelper; import org.hibernate.metamodel.spi.binding.AttributeBinding; import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.metamodel.spi.binding.RelationalValueBinding; @@ -42,7 +42,6 @@ import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource; import org.hibernate.metamodel.spi.source.LocalBindingContext; - import org.jboss.logging.Logger; /** @@ -160,35 +159,11 @@ public class ForeignKeyHelper { final List sourceColumns, final TableSpecification targetTable, final List targetColumns) { - final String foreignKeyName; - if ( StringHelper.isEmpty( explicitForeignKeyName ) ) { - foreignKeyName = ForeignKey.generateName( sourceTable, targetTable, sourceColumns, targetColumns ); - } - else { - foreignKeyName = helperContext.relationalIdentifierHelper().quotedIdentifier( explicitForeignKeyName ); - } + final String foreignKeyName = helperContext.relationalIdentifierHelper().normalizeDatabaseIdentifier( + explicitForeignKeyName, new ForeignKeyNamingStrategyHelper( + sourceTable, sourceColumns, targetTable, targetColumns ) ); ForeignKey foreignKey = locateAndBindForeignKeyByName( foreignKeyName, sourceTable, sourceColumns, targetTable, targetColumns ); - if ( foreignKey == null ) { - foreignKey = locateForeignKeyByColumnMapping( sourceTable, sourceColumns, targetTable, targetColumns ); - if ( foreignKey != null ) { - if ( foreignKey.getName() == null ) { - // the foreign key name has not be initialized; set it to foreignKeyName - foreignKey.setName( foreignKeyName ); - } - else { - // the foreign key name has already been initialized so cannot rename it - // TODO: should this just be INFO? - log.warn( - String.format( - "A foreign key mapped as %s will not be created because foreign key %s already exists with the same column mapping.", - foreignKeyName, - foreignKey.getName() - ) - ); - } - } - } if ( foreignKey == null ) { // no foreign key found; create one foreignKey = sourceTable.createForeignKey( targetTable, foreignKeyName ); @@ -197,27 +172,6 @@ public class ForeignKeyHelper { return foreignKey; } - private static ForeignKey locateForeignKeyByColumnMapping( - final TableSpecification sourceTable, - final List sourceColumns, - final TableSpecification targetTable, - final List targetColumns) { - // check for an existing foreign key with the same source/target columns - ForeignKey foreignKey = null; - Iterable possibleForeignKeys = sourceTable.locateForeignKey( targetTable ); - if ( possibleForeignKeys != null ) { - for ( ForeignKey possibleFK : possibleForeignKeys ) { - if ( possibleFK.getSourceColumns().equals( sourceColumns ) && - possibleFK.getTargetColumns().equals( targetColumns ) ) { - // this is the foreign key - foreignKey = possibleFK; - break; - } - } - } - return foreignKey; - } - private void bindForeignKeyColumns( final ForeignKey foreignKey, final TableSpecification sourceTable, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HashedNameUtil.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HashedNameUtil.java index 2c344b9bdf..e4a83862c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HashedNameUtil.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/HashedNameUtil.java @@ -27,8 +27,6 @@ import java.util.Arrays; import java.util.List; import org.hibernate.HibernateException; -import org.hibernate.metamodel.spi.relational.AbstractConstraint; -import org.hibernate.metamodel.spi.relational.Column; import org.hibernate.metamodel.spi.relational.TableSpecification; /** @@ -47,11 +45,11 @@ public class HashedNameUtil { * @param columnNames * @return String The generated name */ - public static String generateName(String prefix, TableSpecification table, String... columnNames ) { + public static String generateName(String prefix, String tableName, String... columnNames ) { // Use a concatenation that guarantees uniqueness, even if identical names // exist between all table and column identifiers. - StringBuilder sb = new StringBuilder( "table`" + table.getLogicalName().getText() + "`" ); + StringBuilder sb = new StringBuilder( "table`" + tableName + "`" ); // Ensure a consistent ordering of columns, regardless of the order // they were bound. @@ -73,20 +71,12 @@ public class HashedNameUtil { * @param columns * @return String The generated name */ - public static String generateName(String prefix, TableSpecification table, List columns) { - String[] columnNames = new String[columns.size()]; - for ( int i = 0; i < columns.size(); i++ ) { - columnNames[i] = columns.get( i ).getColumnName().getText(); + public static String generateName(String prefix, String tableName, List columnNames) { + String[] columnNamesArray = new String[columnNames.size()]; + for ( int i = 0; i < columnNames.size(); i++ ) { + columnNamesArray[i] = columnNames.get( i ); } - return generateName( prefix, table, columnNames ); - } - - /** - * Helper method for {@link #generateName(String, TableSpecification, String...)}. - * Generates and sets a name for an existing constraint. - */ - public static void setName(String prefix, AbstractConstraint constraint) { - constraint.setName( generateName( prefix, constraint.getTable(), constraint.getColumns() ) ); + return generateName( prefix, tableName, columnNamesArray ); } /** diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/NaturalIdUniqueKeyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/NaturalIdUniqueKeyHelper.java index 62d5b3fbc0..4908bffcae 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/NaturalIdUniqueKeyHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/NaturalIdUniqueKeyHelper.java @@ -31,9 +31,15 @@ import org.hibernate.metamodel.spi.relational.UniqueKey; * @author Brett Meyer */ public class NaturalIdUniqueKeyHelper { + + private final HelperContext helperContext; private Map naturalIdUniqueKeys = new HashMap(); + + public NaturalIdUniqueKeyHelper(HelperContext helperContext) { + this.helperContext = helperContext; + } /** * Natural ID columns must reside in one single UniqueKey within the Table. @@ -50,6 +56,7 @@ public class NaturalIdUniqueKeyHelper { uniqueKey = naturalIdUniqueKeys.get( table ); } else { + // TODO: For now, leave this out of the naming strategy. It has nothing to do with the columns. String keyName = "UK_" + HashedNameUtil.hashedName( table.getLogicalName().getText() + "_NaturalID" ); uniqueKey = new UniqueKey(); uniqueKey.setTable( table ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableHelper.java index 056e58ad2d..76ec7d871d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/TableHelper.java @@ -23,13 +23,17 @@ */ package org.hibernate.metamodel.internal; -import org.jboss.logging.Logger; +import java.util.List; import org.hibernate.TruthValue; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.ConstraintNamingStrategyHelper.IndexNamingStrategyHelper; +import org.hibernate.metamodel.internal.ConstraintNamingStrategyHelper.UniqueKeyNamingStrategyHelper; import org.hibernate.metamodel.spi.relational.Column; import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Index; import org.hibernate.metamodel.spi.relational.Schema; import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.metamodel.spi.relational.TableSpecification; @@ -41,6 +45,7 @@ import org.hibernate.metamodel.spi.source.MappingDefaults; import org.hibernate.metamodel.spi.source.SizeSource; import org.hibernate.metamodel.spi.source.TableSource; import org.hibernate.metamodel.spi.source.TableSpecificationSource; +import org.jboss.logging.Logger; /** * @author Gail Badner @@ -173,14 +178,42 @@ public class TableHelper { column.setComment( columnSource.getComment() ); if (columnSource.isUnique()) { - UniqueKey uk = new UniqueKey(); - uk.addColumn( column ); - uk.setTable( table ); - HashedNameUtil.setName("UK_", uk); - table.addUniqueKey( uk ); + createUniqueKey( table, CollectionHelper.singleEntryList( column ), null ); } return column; } + + public void createUniqueKey( + final TableSpecification table, + final List columns, + final String name) { + final UniqueKey uk = new UniqueKey(); + for ( final Column column : columns ) { + uk.addColumn( column ); + } + uk.setTable( table ); + + final String normalizedName = normalizeDatabaseIdentifier( name, new UniqueKeyNamingStrategyHelper( table, columns ) ); + + uk.setName( normalizedName ); + table.addUniqueKey( uk ); + } + + public void createIndex( + final TableSpecification table, + final List columns, + final String name) { + final Index idx = new Index(); + for ( final Column column : columns ) { + idx.addColumn( column ); + } + idx.setTable( table ); + + final String normalizedName = normalizeDatabaseIdentifier( name, new IndexNamingStrategyHelper( table, columns ) ); + + idx.setName( normalizedName ); + table.addIndex( idx ); + } private void resolveColumnNullable( final TableSpecification table, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java index e441cc0435..be11f276ef 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java @@ -25,10 +25,6 @@ package org.hibernate.metamodel.internal.source.annotations.global; import java.util.Collection; -import org.jboss.jandex.AnnotationInstance; -import org.jboss.logging.Logger; - -import org.hibernate.AnnotationException; import org.hibernate.MappingException; import org.hibernate.annotations.FetchMode; import org.hibernate.internal.CoreMessageLogger; @@ -40,12 +36,11 @@ import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotName import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.metamodel.spi.binding.SecondaryTable; -import org.hibernate.metamodel.spi.relational.Column; -import org.hibernate.metamodel.spi.relational.Index; import org.hibernate.metamodel.spi.relational.ObjectName; import org.hibernate.metamodel.spi.relational.Schema; import org.hibernate.metamodel.spi.relational.Table; -import org.hibernate.metamodel.spi.relational.Value; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.logging.Logger; /** * Binds table related information. This binder is called after the entities are bound. @@ -101,13 +96,6 @@ public class TableProcessor { final AnnotationInstance tableAnnotation, final boolean isSecondaryTable, final MetadataImplementor metadata) { - for ( AnnotationInstance indexAnnotation : JandexHelper.getValue( - tableAnnotation, - "indexes", - AnnotationInstance[].class - ) ) { - bindIndexAnnotation( table, tableAnnotation, indexAnnotation ); - } String comment = JandexHelper.getValue( tableAnnotation, "comment", String.class ); if ( StringHelper.isNotEmpty( comment ) ) { table.addComment( comment.trim() ); @@ -164,35 +152,4 @@ public class TableProcessor { } - - private static void bindIndexAnnotation(Table table, AnnotationInstance tableAnnotation, AnnotationInstance indexAnnotation) { - String indexName = JandexHelper.getValue( indexAnnotation, "name", String.class ); - String[] columnNames = JandexHelper.getValue( indexAnnotation, "columnNames", String[].class ); - if ( columnNames == null ) { - LOG.noColumnsSpecifiedForIndex( indexName, table.toLoggableString() ); - return; - } - Index index = table.getOrCreateIndex( indexName ); - for ( String columnName : columnNames ) { - Column column = findColumn( table, columnName ); - if ( column == null ) { - throw new AnnotationException( "@Index references a unknown column: " + columnName ); - } - index.addColumn( column ); - } - } - - private static Column findColumn(Table table, String columnName) { - Column column = null; - for ( Value value : table.values() ) { - if ( Column.class.isInstance( value ) && Column.class.cast( value ) - .getColumnName() - .getText() - .equals( columnName ) ) { - column = (Column) value; - break; - } - } - return column; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ForeignKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ForeignKey.java index f4657ff893..44f35afdc2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ForeignKey.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ForeignKey.java @@ -24,16 +24,13 @@ package org.hibernate.metamodel.spi.relational; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.Iterator; import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.MappingException; import org.hibernate.dialect.Dialect; -import org.hibernate.metamodel.internal.HashedNameUtil; import org.jboss.logging.Logger; /** @@ -260,51 +257,6 @@ public class ForeignKey extends AbstractConstraint { return columnMappingList; } - /** - * If a constraint is not explicitly named, this is called to generate - * a unique hash using the source/target table and column names. - * Static so the name can be generated prior to creating the Constraint. - * They're cached, keyed by name, in multiple locations. - * - * @param sourceTable - * @param targetTable - * @param sourceColumns - * @param targetColumns - * @return String The generated name - */ - public static String generateName(TableSpecification sourceTable, TableSpecification targetTable, - List sourceColumns, List targetColumns) { - // Use a concatenation that guarantees uniqueness, even if identical names - // exist between all table and column identifiers. - - StringBuilder sb = new StringBuilder( "table`" + sourceTable.getLogicalName().getText() + "`" ); - sb.append( "table`" + targetTable.getLogicalName().getText() + "`" ); - appendColumns( sourceColumns, sb ); - appendColumns( targetColumns, sb ); - - return "FK_" + HashedNameUtil.hashedName( sb.toString() ); - } - - private static void appendColumns(List columns, StringBuilder sb) { - // Ensure a consistent ordering of columns, regardless of the order - // they were bound. - // Clone the list, as sometimes a set of order-dependent Column - // bindings are given. - Column[] alphabeticalColumns = columns.toArray( new Column[columns.size()] ); - Arrays.sort( alphabeticalColumns, ColumnComparator.INSTANCE ); - for ( Column column : alphabeticalColumns ) { - sb.append( "column`" + column.getColumnName().getText() + "`" ); - } - } - - private static class ColumnComparator implements Comparator { - public static ColumnComparator INSTANCE = new ColumnComparator(); - - public int compare(Column col1, Column col2) { - return col1.getColumnName().toString().compareTo( col2.getColumnName().toString() ); - } - } - @Override public String getExportIdentifier() { return getSourceTable().getLoggableValueQualifier() + ".FK-" + getName(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InLineView.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InLineView.java index 96f7816dd6..adc0aeee13 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InLineView.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InLineView.java @@ -69,7 +69,7 @@ public class InLineView extends AbstractTableSpecification { } @Override - public Index getOrCreateIndex(String name) { + public void addIndex(Index index) { throw new UnsupportedOperationException( "Cannot create index on inline view" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Index.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Index.java index cfa75cb982..b88649de39 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Index.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Index.java @@ -33,6 +33,10 @@ import org.hibernate.dialect.Dialect; */ public class Index extends AbstractConstraint { + public Index() { + this( null, null ); + } + protected Index(Table table, String name) { super( table, name ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java index ae6cbebeb2..20ddbd568e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java @@ -147,16 +147,8 @@ public class Table extends AbstractTableSpecification implements Exportable { } @Override - public Index getOrCreateIndex(String name) { - Index result = null; - if ( name != null ) { - result = locateConstraint( indexes, name ); - } - if ( result == null ) { - result = new Index( this, name ); - indexes.add( result ); - } - return result; + public void addIndex(Index idx) { + indexes.add( idx ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java index a9c9f74265..46503428fd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java @@ -136,7 +136,7 @@ public interface TableSpecification extends ValueContainer, Loggable { public Iterable getIndexes(); - public Index getOrCreateIndex(String name); + public void addIndex(Index idx); public Iterable getUniqueKeys();