diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java b/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java
index daf65689f8..719e3798d8 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java
@@ -1378,11 +1378,9 @@ public class Configuration implements Serializable {
for ( Map.Entry
> tableListEntry : uniqueConstraintHoldersByTable.entrySet() ) {
final Table table = tableListEntry.getKey();
final List uniqueConstraints = tableListEntry.getValue();
- int uniqueIndexPerTable = 0;
for ( UniqueConstraintHolder holder : uniqueConstraints ) {
- uniqueIndexPerTable++;
final String keyName = StringHelper.isEmpty( holder.getName() )
- ? "UK_" + table.getName() + "_" + uniqueIndexPerTable
+ ? StringHelper.randomFixedLengthHex("UK_")
: holder.getName();
buildUniqueKeyFromColumnNames( table, keyName, holder.getColumns() );
}
diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java
index f982ec33cb..ea3f476416 100644
--- a/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java
@@ -29,6 +29,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.StringTokenizer;
+import java.util.UUID;
import org.hibernate.dialect.Dialect;
import org.hibernate.internal.util.collections.ArrayHelper;
@@ -758,4 +759,18 @@ public final class StringHelper {
public static String[] toArrayElement(String s) {
return ( s == null || s.length() == 0 ) ? new String[0] : new String[] { s };
}
+
+ // Oracle restricts identifier lengths to 30. Rather than tie this to
+ // Dialect, simply restrict randomly-generated constrain names across
+ // the board.
+ private static final int MAX_NAME_LENGTH = 30;
+ public static String randomFixedLengthHex(String prefix) {
+ int length = MAX_NAME_LENGTH - prefix.length();
+ String s = UUID.randomUUID().toString();
+ s = s.replace( "-", "" );
+ if (s.length() > length) {
+ s = s.substring( 0, length );
+ }
+ return prefix + s;
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java
index 488ebaab33..05fbdd10aa 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java
@@ -35,6 +35,7 @@ import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.Mapping;
+import org.hibernate.internal.util.StringHelper;
import org.hibernate.tool.hbm2ddl.ColumnMetadata;
import org.hibernate.tool.hbm2ddl.TableMetadata;
@@ -394,8 +395,6 @@ public class Table implements RelationalModel, Serializable {
Iterator iter = getColumnIterator();
List results = new ArrayList();
- int uniqueIndexInteger = 0;
-
while ( iter.hasNext() ) {
Column column = (Column) iter.next();
@@ -422,9 +421,8 @@ public class Table implements RelationalModel, Serializable {
}
if ( column.isUnique() ) {
- uniqueIndexInteger++;
UniqueKey uk = getOrCreateUniqueKey(
- "UK_" + name + "_" + uniqueIndexInteger);
+ StringHelper.randomFixedLengthHex("UK_"));
uk.addColumn( column );
alter.append( dialect.getUniqueDelegate()
.applyUniqueToColumn( column ) );
@@ -493,7 +491,6 @@ public class Table implements RelationalModel, Serializable {
}
Iterator iter = getColumnIterator();
- int uniqueIndexInteger = 0;
while ( iter.hasNext() ) {
Column col = (Column) iter.next();
@@ -527,9 +524,8 @@ public class Table implements RelationalModel, Serializable {
}
if ( col.isUnique() ) {
- uniqueIndexInteger++;
UniqueKey uk = getOrCreateUniqueKey(
- "uc_" + name + "_" + uniqueIndexInteger);
+ StringHelper.randomFixedLengthHex("UK_"));
uk.addColumn( col );
buf.append( dialect.getUniqueDelegate()
.applyUniqueToColumn( col ) );
@@ -625,7 +621,7 @@ public class Table implements RelationalModel, Serializable {
}
public UniqueKey createUniqueKey(List keyColumns) {
- String keyName = "UK_" + uniqueColumnString( keyColumns.iterator() );
+ String keyName = StringHelper.randomFixedLengthHex("UK_");
UniqueKey uk = getOrCreateUniqueKey( keyName );
uk.addColumns( keyColumns.iterator() );
return uk;
@@ -665,9 +661,7 @@ public class Table implements RelationalModel, Serializable {
fk.setName( keyName );
}
else {
- fk.setName( "FK" + uniqueColumnString( keyColumns.iterator(), referencedEntityName ) );
- //TODO: add referencedClass to disambiguate to FKs on the same
- // columns, pointing to different tables
+ fk.setName( StringHelper.randomFixedLengthHex("FK_") );
}
fk.setTable( this );
foreignKeys.put( key, fk );
@@ -686,22 +680,6 @@ public class Table implements RelationalModel, Serializable {
}
- public String uniqueColumnString(Iterator iterator) {
- return uniqueColumnString( iterator, null );
- }
-
- public String uniqueColumnString(Iterator iterator, String referencedEntityName) {
- int result = 0;
- if ( referencedEntityName != null ) {
- result += referencedEntityName.hashCode();
- }
- while ( iterator.hasNext() ) {
- result += iterator.next().hashCode();
- }
- return ( Integer.toHexString( name.hashCode() ) + Integer.toHexString( result ) ).toUpperCase();
- }
-
-
public String getSchema() {
return schema;
diff --git a/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java b/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java
index 5685d986d8..0e33a4ff83 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java
@@ -20,57 +20,100 @@
*/
package org.hibernate.test.constraint;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import java.util.Iterator;
+
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
+import javax.persistence.OneToOne;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import org.hibernate.mapping.Column;
+import org.hibernate.mapping.ForeignKey;
+import org.hibernate.mapping.UniqueKey;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
-/**
- * HHH-7797 re-wrote the way dialects handle unique constraints. Test
- * variations of unique & not null to ensure the constraints are created
- * correctly for each dialect.
- *
- * @author Brett Meyer
- */
-@TestForIssue( jiraKey = "HHH-7797" )
public class ConstraintTest extends BaseCoreFunctionalTestCase {
+ private static final int MAX_NAME_LENGTH = 30;
+
+ private static final String EXPLICIT_FK_NAME = "fk_explicit";
+
+ private static final String EXPLICIT_UK_NAME = "uk_explicit";
+
@Override
protected Class>[] getAnnotatedClasses() {
return new Class>[] {
- Entity1.class
+ DataPoint.class, DataPoint2.class
};
}
@Test
- public void testConstraints() {
- Column column = (Column) configuration().getClassMapping( Entity1.class.getName() )
+ @TestForIssue( jiraKey = "HHH-7797" )
+ public void testUniqueConstraints() {
+ Column column = (Column) configuration().getClassMapping( DataPoint.class.getName() )
.getProperty( "foo1" ).getColumnIterator().next();
assertFalse( column.isNullable() );
assertTrue( column.isUnique() );
- column = (Column) configuration().getClassMapping( Entity1.class.getName() )
+ column = (Column) configuration().getClassMapping( DataPoint.class.getName() )
.getProperty( "foo2" ).getColumnIterator().next();
assertTrue( column.isNullable() );
assertTrue( column.isUnique() );
- column = (Column) configuration().getClassMapping( Entity1.class.getName() )
+ column = (Column) configuration().getClassMapping( DataPoint.class.getName() )
.getProperty( "id" ).getColumnIterator().next();
assertFalse( column.isNullable() );
assertTrue( column.isUnique() );
}
+ @Test
+ @TestForIssue( jiraKey = "HHH-1904" )
+ public void testConstraintNameLength() {
+ Iterator tableItr = configuration().getTableMappings();
+ while (tableItr.hasNext()) {
+ org.hibernate.mapping.Table table = tableItr.next();
+
+ Iterator fkItr = table.getForeignKeyIterator();
+ while (fkItr.hasNext()) {
+ ForeignKey fk = (ForeignKey) fkItr.next();
+ assertTrue( fk.getName().length() <= MAX_NAME_LENGTH );
+
+ // ensure the randomly generated constraint name doesn't
+ // happen if explicitly given
+ Column column = fk.getColumn( 0 );
+ if ( column.getName().equals( "explicit" ) ) {
+ assertEquals( fk.getName(), EXPLICIT_FK_NAME );
+ }
+ }
+
+ Iterator ukItr = table.getUniqueKeyIterator();
+ while (ukItr.hasNext()) {
+ UniqueKey uk = (UniqueKey) ukItr.next();
+ assertTrue( uk.getName().length() <= MAX_NAME_LENGTH );
+
+ // ensure the randomly generated constraint name doesn't
+ // happen if explicitly given
+ Column column = uk.getColumn( 0 );
+ if ( column.getName().equals( "explicit" ) ) {
+ assertEquals( uk.getName(), EXPLICIT_UK_NAME );
+ }
+ }
+ }
+ }
+
@Entity
- @Table( name = "Entity1" )
- public static class Entity1 {
+ @Table( name = "DataPoint", uniqueConstraints = {
+ @UniqueConstraint( name = EXPLICIT_UK_NAME, columnNames = { "explicit" } )
+ } )
+ public static class DataPoint {
@Id
@GeneratedValue
@javax.persistence.Column( nullable = false, unique = true)
@@ -81,5 +124,22 @@ public class ConstraintTest extends BaseCoreFunctionalTestCase {
@javax.persistence.Column( nullable = true, unique = true)
public String foo2;
+
+ public String explicit;
+ }
+
+ @Entity
+ @Table( name = "DataPoint2" )
+ public static class DataPoint2 {
+ @Id
+ @GeneratedValue
+ public long id;
+
+ @OneToOne
+ public DataPoint dp;
+
+ @OneToOne
+ @org.hibernate.annotations.ForeignKey(name = EXPLICIT_FK_NAME)
+ public DataPoint explicit;
}
}
\ No newline at end of file