HHH-1904 Identifier too long
Conflicts: hibernate-core/src/main/java/org/hibernate/mapping/Table.java
This commit is contained in:
parent
d9673b8a70
commit
4f0344dbbe
|
@ -1372,11 +1372,9 @@ public class Configuration implements Serializable {
|
|||
for ( Map.Entry<Table, List<UniqueConstraintHolder>> tableListEntry : uniqueConstraintHoldersByTable.entrySet() ) {
|
||||
final Table table = tableListEntry.getKey();
|
||||
final List<UniqueConstraintHolder> 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() );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,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;
|
||||
|
||||
|
@ -395,8 +396,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();
|
||||
|
||||
|
@ -423,9 +422,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 ) );
|
||||
|
@ -494,7 +492,6 @@ public class Table implements RelationalModel, Serializable {
|
|||
}
|
||||
|
||||
Iterator iter = getColumnIterator();
|
||||
int uniqueIndexInteger = 0;
|
||||
while ( iter.hasNext() ) {
|
||||
Column col = (Column) iter.next();
|
||||
|
||||
|
@ -528,9 +525,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 ) );
|
||||
|
@ -626,7 +622,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;
|
||||
|
@ -666,9 +662,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,23 +680,6 @@ public class Table implements RelationalModel, Serializable {
|
|||
return fk;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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<org.hibernate.mapping.Table> 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue