org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-core Show documentation
Show all versions of hibernate-core Show documentation
Hibernate's core ORM functionality
/*
* 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 .
*/
package org.hibernate.boot.model.naming;
import java.io.Serializable;
import org.hibernate.HibernateException;
import org.hibernate.boot.model.source.spi.AttributePath;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.internal.util.StringHelper;
/**
* Implementation of the ImplicitNamingStrategy contract, generally preferring to conform
* to JPA standards.
*
* For the legacy JPA-based naming standards initially implemented by Hibernate,
* see/use {@link org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl}
*
* @author Steve Ebersole
*/
public class ImplicitNamingStrategyJpaCompliantImpl implements ImplicitNamingStrategy, Serializable {
public static final ImplicitNamingStrategy INSTANCE = new ImplicitNamingStrategyJpaCompliantImpl();
public ImplicitNamingStrategyJpaCompliantImpl() {
}
@Override
public Identifier determinePrimaryTableName(ImplicitEntityNameSource source) {
if ( source == null ) {
// should never happen, but to be defensive...
throw new HibernateException( "Entity naming information was not provided." );
}
String tableName = transformEntityName( source.getEntityNaming() );
if ( tableName == null ) {
// todo : add info to error message - but how to know what to write since we failed to interpret the naming source
throw new HibernateException( "Could not determine primary table name for entity" );
}
return toIdentifier( tableName, source.getBuildingContext() );
}
protected String transformEntityName(EntityNaming entityNaming) {
// prefer the JPA entity name, if specified...
if ( StringHelper.isNotEmpty( entityNaming.getJpaEntityName() ) ) {
return entityNaming.getJpaEntityName();
}
else {
// otherwise, use the Hibernate entity name
return StringHelper.unqualify( entityNaming.getEntityName() );
}
}
@Override
public Identifier determineJoinTableName(ImplicitJoinTableNameSource source) {
// JPA states we should use the following as default:
// "The concatenated names of the two associated primary entity tables (owning side
// first), separated by an underscore."
// aka:
// {OWNING SIDE PRIMARY TABLE NAME}_{NON-OWNING SIDE PRIMARY TABLE NAME}
final String name = source.getOwningPhysicalTableName()
+ '_'
+ source.getNonOwningPhysicalTableName();
return toIdentifier( name, source.getBuildingContext() );
}
@Override
public Identifier determineCollectionTableName(ImplicitCollectionTableNameSource source) {
// JPA states we should use the following as default:
// "The concatenation of the name of the containing entity and the name of the
// collection attribute, separated by an underscore.
// aka:
// if owning entity has a JPA entity name: {OWNER JPA ENTITY NAME}_{COLLECTION ATTRIBUTE NAME}
// otherwise: {OWNER ENTITY NAME}_{COLLECTION ATTRIBUTE NAME}
final String entityName = transformEntityName( source.getOwningEntityNaming() );
final String name = entityName
+ '_'
+ transformAttributePath( source.getOwningAttributePath() );
return toIdentifier( name, source.getBuildingContext() );
}
@Override
public Identifier determineIdentifierColumnName(ImplicitIdentifierColumnNameSource source) {
// JPA states the implicit column name should be the attribute name
return toIdentifier(
transformAttributePath( source.getIdentifierAttributePath() ),
source.getBuildingContext()
);
}
@Override
public Identifier determineDiscriminatorColumnName(ImplicitDiscriminatorColumnNameSource source) {
return toIdentifier(
source.getBuildingContext().getMappingDefaults().getImplicitDiscriminatorColumnName(),
source.getBuildingContext()
);
}
@Override
public Identifier determineTenantIdColumnName(ImplicitTenantIdColumnNameSource source) {
return toIdentifier(
source.getBuildingContext().getMappingDefaults().getImplicitTenantIdColumnName(),
source.getBuildingContext()
);
}
@Override
public Identifier determineBasicColumnName(ImplicitBasicColumnNameSource source) {
// JPA states we should use the following as default:
// "The property or field name"
// aka:
// The unqualified attribute path.
return toIdentifier( transformAttributePath( source.getAttributePath() ), source.getBuildingContext() );
}
@Override
public Identifier determineJoinColumnName(ImplicitJoinColumnNameSource source) {
// JPA states we should use the following as default:
//
// (1) if there is a "referencing relationship property":
// "The concatenation of the following: the name of the referencing relationship
// property or field of the referencing entity or embeddable class; "_"; the
// name of the referenced primary key column."
//
// (2) if there is no such "referencing relationship property", or if the association is
// an element collection:
// "The concatenation of the following: the name of the entity; "_"; the name of the
// referenced primary key column"
// todo : we need to better account for "referencing relationship property"
final String name;
if ( source.getNature() == ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION
|| source.getAttributePath() == null ) {
name = transformEntityName( source.getEntityNaming() )
+ '_'
+ source.getReferencedColumnName().getText();
}
else {
name = transformAttributePath( source.getAttributePath() )
+ '_'
+ source.getReferencedColumnName().getText();
}
return toIdentifier( name, source.getBuildingContext() );
}
@Override
public Identifier determinePrimaryKeyJoinColumnName(ImplicitPrimaryKeyJoinColumnNameSource source) {
// JPA states we should use the following as default:
// "the same name as the primary key column [of the referenced table]"
return source.getReferencedPrimaryKeyColumnName();
}
@Override
public Identifier determineAnyDiscriminatorColumnName(ImplicitAnyDiscriminatorColumnNameSource source) {
return toIdentifier(
transformAttributePath( source.getAttributePath() ) + "_" + source.getBuildingContext().getMappingDefaults().getImplicitDiscriminatorColumnName(),
source.getBuildingContext()
);
}
@Override
public Identifier determineAnyKeyColumnName(ImplicitAnyKeyColumnNameSource source) {
return toIdentifier(
transformAttributePath( source.getAttributePath() ) + "_" + source.getBuildingContext().getMappingDefaults().getImplicitIdColumnName(),
source.getBuildingContext()
);
}
@Override
public Identifier determineMapKeyColumnName(ImplicitMapKeyColumnNameSource source) {
return toIdentifier(
transformAttributePath( source.getPluralAttributePath() ) + "_KEY",
source.getBuildingContext()
);
}
@Override
public Identifier determineListIndexColumnName(ImplicitIndexColumnNameSource source) {
return toIdentifier(
transformAttributePath( source.getPluralAttributePath() ) + "_ORDER",
source.getBuildingContext()
);
}
@Override
public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.withCharset( source.getBuildingContext().getBuildingOptions().getSchemaCharset() ).generateHashedFkName(
"FK",
source.getTableName(),
source.getReferencedTableName(),
source.getColumnNames()
),
source.getBuildingContext()
);
}
@Override
public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source) {
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.withCharset( source.getBuildingContext().getBuildingOptions().getSchemaCharset() ).generateHashedConstraintName(
"UK",
source.getTableName(),
source.getColumnNames()
),
source.getBuildingContext()
);
}
@Override
public Identifier determineIndexName(ImplicitIndexNameSource source) {
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.withCharset( source.getBuildingContext().getBuildingOptions().getSchemaCharset() ).generateHashedConstraintName(
"IDX",
source.getTableName(),
source.getColumnNames()
),
source.getBuildingContext()
);
}
/**
* For JPA standards we typically need the unqualified name. However, a more usable
* impl tends to use the whole path. This method provides an easy hook for subclasses
* to accomplish that
*
* @param attributePath The attribute path
*
* @return The extracted name
*/
protected String transformAttributePath(AttributePath attributePath) {
return attributePath.getProperty();
}
/**
* Easy hook to build an Identifier using the keyword safe IdentifierHelper.
*
* @param stringForm The String form of the name
* @param buildingContext Access to the IdentifierHelper
*
* @return The identifier
*/
protected Identifier toIdentifier(String stringForm, MetadataBuildingContext buildingContext) {
return buildingContext.getMetadataCollector()
.getDatabase()
.getJdbcEnvironment()
.getIdentifierHelper()
.toIdentifier( stringForm );
}
}