HHH-11089 - Naming Strategy Does not affect the user-specified index/foreign-key names

Call the implicit naming strategy regardless if the client has specified foreign key name or not
This commit is contained in:
petar.tahchiev 2017-02-18 17:47:58 +02:00 committed by Vlad Mihalcea
parent e0da35e5e8
commit e654e6c2c7
6 changed files with 293 additions and 82 deletions

View File

@ -1811,45 +1811,49 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
fk.setReferencedTable( referencedClass.getTable() );
// todo : should we apply a physical naming too?
if ( fk.getName() == null ) {
final Identifier nameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy().determineForeignKeyName(
new ImplicitForeignKeyNameSource() {
final List<Identifier> columnNames = extractColumnNames( fk.getColumns() );
List<Identifier> referencedColumnNames = null;
Identifier nameIdentifier;
@Override
public Identifier getTableName() {
return table.getNameIdentifier();
}
ImplicitForeignKeyNameSource foreignKeyNameSource = new ImplicitForeignKeyNameSource() {
final List<Identifier> columnNames = extractColumnNames( fk.getColumns() );
List<Identifier> referencedColumnNames = null;
@Override
public List<Identifier> getColumnNames() {
return columnNames;
}
@Override
public Identifier getTableName() {
return table.getNameIdentifier();
}
@Override
public Identifier getReferencedTableName() {
return fk.getReferencedTable().getNameIdentifier();
}
@Override
public List<Identifier> getColumnNames() {
return columnNames;
}
@Override
public List<Identifier> getReferencedColumnNames() {
if ( referencedColumnNames == null ) {
referencedColumnNames = extractColumnNames( fk.getReferencedColumns() );
}
return referencedColumnNames;
}
@Override
public Identifier getReferencedTableName() {
return fk.getReferencedTable().getNameIdentifier();
}
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
}
}
);
@Override
public List<Identifier> getReferencedColumnNames() {
if ( referencedColumnNames == null ) {
referencedColumnNames = extractColumnNames( fk.getReferencedColumns() );
}
return referencedColumnNames;
}
fk.setName( nameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() ) );
}
@Override
public Identifier getUserProvidedIdentifier() {
return fk.getName() != null ? Identifier.toIdentifier( fk.getName() ) : null;
}
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
}
};
nameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy().determineForeignKeyName(foreignKeyNameSource);
fk.setName( nameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() ) );
fk.alignColumns();
}
@ -1959,34 +1963,39 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
}
}
final String originalKeyName = keyName;
if ( unique ) {
if ( StringHelper.isEmpty( keyName ) ) {
final Identifier keyNameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy().determineUniqueKeyName(
new ImplicitUniqueKeyNameSource() {
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
}
final Identifier keyNameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy().determineUniqueKeyName(
new ImplicitUniqueKeyNameSource() {
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
}
@Override
public Identifier getTableName() {
return table.getNameIdentifier();
}
@Override
public Identifier getTableName() {
return table.getNameIdentifier();
}
private List<Identifier> columnNameIdentifiers;
private List<Identifier> columnNameIdentifiers;
@Override
public List<Identifier> getColumnNames() {
// be lazy about building these
if ( columnNameIdentifiers == null ) {
columnNameIdentifiers = toIdentifiers( columnNames );
}
return columnNameIdentifiers;
}
@Override
public List<Identifier> getColumnNames() {
// be lazy about building these
if ( columnNameIdentifiers == null ) {
columnNameIdentifiers = toIdentifiers( columnNames );
}
);
keyName = keyNameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() );
}
return columnNameIdentifiers;
}
@Override
public Identifier getUserProvidedIdentifier() {
return originalKeyName != null ? Identifier.toIdentifier( originalKeyName ) : null;
}
}
);
keyName = keyNameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() );
UniqueKey uk = table.getOrCreateUniqueKey( keyName );
for ( int i = 0; i < columns.length; i++ ) {
@ -1999,33 +2008,36 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
}
}
else {
if ( StringHelper.isEmpty( keyName ) ) {
final Identifier keyNameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy().determineIndexName(
new ImplicitIndexNameSource() {
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
}
final Identifier keyNameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy().determineIndexName(
new ImplicitIndexNameSource() {
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
}
@Override
public Identifier getTableName() {
return table.getNameIdentifier();
}
@Override
public Identifier getTableName() {
return table.getNameIdentifier();
}
private List<Identifier> columnNameIdentifiers;
private List<Identifier> columnNameIdentifiers;
@Override
public List<Identifier> getColumnNames() {
// be lazy about building these
if ( columnNameIdentifiers == null ) {
columnNameIdentifiers = toIdentifiers( columnNames );
}
return columnNameIdentifiers;
}
@Override
public List<Identifier> getColumnNames() {
// be lazy about building these
if ( columnNameIdentifiers == null ) {
columnNameIdentifiers = toIdentifiers( columnNames );
}
);
keyName = keyNameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() );
}
return columnNameIdentifiers;
}
@Override
public Identifier getUserProvidedIdentifier() {
return originalKeyName != null ? Identifier.toIdentifier( originalKeyName ) : null;
}
}
);
keyName = keyNameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() );
Index index = table.getOrCreateIndex( keyName );
for ( int i = 0; i < columns.length; i++ ) {

View File

@ -16,4 +16,5 @@ import java.util.List;
public interface ImplicitConstraintNameSource extends ImplicitNameSource {
public Identifier getTableName();
public List<Identifier> getColumnNames();
public Identifier getUserProvidedIdentifier();
}

View File

@ -198,7 +198,8 @@ public class ImplicitNamingStrategyJpaCompliantImpl implements ImplicitNamingStr
@Override
public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {
return toIdentifier(
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.INSTANCE.generateHashedFkName(
"FK",
source.getTableName(),
@ -211,7 +212,8 @@ public class ImplicitNamingStrategyJpaCompliantImpl implements ImplicitNamingStr
@Override
public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source) {
return toIdentifier(
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.INSTANCE.generateHashedConstraintName(
"UK",
source.getTableName(),
@ -223,7 +225,8 @@ public class ImplicitNamingStrategyJpaCompliantImpl implements ImplicitNamingStr
@Override
public Identifier determineIndexName(ImplicitIndexNameSource source) {
return toIdentifier(
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.INSTANCE.generateHashedConstraintName(
"IDX",
source.getTableName(),

View File

@ -4345,6 +4345,11 @@ public class ModelBinder {
public MetadataBuildingContext getBuildingContext() {
return mappingDocument;
}
@Override
public Identifier getUserProvidedIdentifier() {
return uk.getName() != null ? Identifier.toIdentifier( uk.getName() ) : null;
}
}
);
uk.setName( ukName.render( mappingDocument.getMetadataCollector().getDatabase().getDialect() ) );

View File

@ -0,0 +1,41 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.annotations.namingstrategy;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitForeignKeyNameSource;
import org.hibernate.boot.model.naming.ImplicitIndexNameSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl;
import org.hibernate.boot.model.naming.ImplicitUniqueKeyNameSource;
@SuppressWarnings("serial")
public class LongIdentifierNamingStrategy
extends ImplicitNamingStrategyJpaCompliantImpl {
@Override
public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {
return limitIdentifierName(super.determineForeignKeyName( source ));
}
@Override
public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source) {
return limitIdentifierName(super.determineUniqueKeyName( source ));
}
@Override
public Identifier determineIndexName(ImplicitIndexNameSource source) {
return limitIdentifierName(super.determineIndexName( source ));
}
public Identifier limitIdentifierName(Identifier identifier) {
String text = identifier.getText();
if(text.length() > 30) {
return new Identifier( text.substring( 0, 30 ), identifier.isQuoted() );
}
return identifier;
}
}

View File

@ -0,0 +1,149 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
// $Id$
package org.hibernate.test.annotations.namingstrategy;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.cfg.Environment;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.jboss.logging.Logger;
import static org.junit.Assert.assertEquals;
/**
* Test harness for HHH-11089.
*
* @author Vlad Mihalcea
*/
@TestForIssue( jiraKey = "HHH-11089" )
public class LongKeyNamingStrategyTest extends BaseUnitTestCase {
private static final Logger log = Logger.getLogger( LongKeyNamingStrategyTest.class );
private ServiceRegistry serviceRegistry;
@Before
public void setUp() {
serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( Environment.getProperties() );
}
@After
public void tearDown() {
if ( serviceRegistry != null ) {
ServiceRegistryBuilder.destroy( serviceRegistry );
}
}
@Test
public void testWithCustomNamingStrategy() throws Exception {
Metadata metadata = new MetadataSources( serviceRegistry )
.addAnnotatedClass(Address.class)
.addAnnotatedClass(Person.class)
.getMetadataBuilder()
.applyImplicitNamingStrategy( new LongIdentifierNamingStrategy() )
.build();
org.hibernate.mapping.ForeignKey foreignKey =
(org.hibernate.mapping.ForeignKey) metadata.getEntityBinding( Address.class.getName()).getTable().getForeignKeyIterator().next();
assertEquals( "FK_way_longer_than_the_30_char", foreignKey.getName() );
UniqueKey uniqueKey = metadata.getEntityBinding( Address.class.getName()).getTable().getUniqueKeyIterator().next();
assertEquals( "UK_way_longer_than_the_30_char", uniqueKey.getName() );
org.hibernate.mapping.Index index = metadata.getEntityBinding( Address.class.getName()).getTable().getIndexIterator().next();
assertEquals( "IDX_way_longer_than_the_30_cha", index.getName() );
}
@Entity(name = "Address")
@Table(uniqueConstraints = @UniqueConstraint(
name = "UK_way_longer_than_the_30_characters_limit",
columnNames = {
"city", "streetName", "streetNumber"
}),
indexes = @Index( name = "IDX_way_longer_than_the_30_characters_limit", columnList = "city, streetName, streetNumber")
)
public class Address {
@Id
private Long id;
private String city;
private String streetName;
private String streetNumber;
@ManyToOne
@JoinColumn(name = "person_id", foreignKey = @ForeignKey(name = "FK_way_longer_than_the_30_characters_limit"))
private Person person;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public String getStreetNumber() {
return streetNumber;
}
public void setStreetNumber(String streetNumber) {
this.streetNumber = streetNumber;
}
}
@Entity
public class Person {
@Id
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
}