HHH-9524 - Make it pluggable how GenerationType.AUTO is mapped

This commit is contained in:
Steve Ebersole 2015-03-26 16:18:40 -05:00
parent 81d30aa037
commit 5d365cfa00
6 changed files with 253 additions and 52 deletions

View File

@ -32,6 +32,7 @@ import org.hibernate.boot.archive.scan.spi.ScanEnvironment;
import org.hibernate.boot.archive.scan.spi.ScanOptions; import org.hibernate.boot.archive.scan.spi.ScanOptions;
import org.hibernate.boot.archive.scan.spi.Scanner; import org.hibernate.boot.archive.scan.spi.Scanner;
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory; import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
import org.hibernate.boot.model.IdGenerationTypeInterpreter;
import org.hibernate.boot.model.TypeContributor; import org.hibernate.boot.model.TypeContributor;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy; import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy; import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
@ -397,6 +398,9 @@ public interface MetadataBuilder {
*/ */
MetadataBuilder applyAttributeConverter(AttributeConverter attributeConverter, boolean autoApply); MetadataBuilder applyAttributeConverter(AttributeConverter attributeConverter, boolean autoApply);
MetadataBuilder applyIdGenerationTypeInterpreter(IdGenerationTypeInterpreter interpreter);
// /** // /**
// * Specify the resolve to be used in identifying the backing members of a // * Specify the resolve to be used in identifying the backing members of a
// * persistent attributes. // * persistent attributes.

View File

@ -0,0 +1,135 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, 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.boot.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.persistence.GenerationType;
import org.hibernate.boot.model.IdGenerationTypeInterpreter;
import org.hibernate.id.MultipleHiLoPerTableGenerator;
import org.hibernate.id.UUIDGenerator;
/**
* The root (composition) IdGenerationTypeInterpreter.
*
* @author Steve Ebersole
*/
public class IdGenerationTypeInterpreterImpl implements IdGenerationTypeInterpreter {
private IdGenerationTypeInterpreter fallbackInterpreter = FallbackInterpreter.INSTANCE;
private ArrayList<IdGenerationTypeInterpreter> delegates;
@Override
public String determineGeneratorName(GenerationType generationType, Context context) {
if ( delegates != null ) {
for ( IdGenerationTypeInterpreter delegate : delegates ) {
final String result = delegate.determineGeneratorName( generationType, context );
if ( result != null ) {
return result;
}
}
}
return fallbackInterpreter.determineGeneratorName( generationType, context );
}
public void enableLegacyFallback() {
fallbackInterpreter = LegacyFallbackInterpreter.INSTANCE;
}
public void disableLegacyFallback() {
fallbackInterpreter = FallbackInterpreter.INSTANCE;
}
public void addInterpreterDelegate(IdGenerationTypeInterpreter delegate) {
if ( delegates == null ) {
delegates = new ArrayList<IdGenerationTypeInterpreter>();
}
delegates.add( delegate );
}
private static class LegacyFallbackInterpreter implements IdGenerationTypeInterpreter {
/**
* Singleton access
*/
public static final LegacyFallbackInterpreter INSTANCE = new LegacyFallbackInterpreter();
@Override
public String determineGeneratorName(GenerationType generationType, Context context) {
switch ( generationType ) {
case IDENTITY: {
return "identity";
}
case SEQUENCE: {
return "seqhilo";
}
case TABLE: {
return MultipleHiLoPerTableGenerator.class.getName();
}
default: {
// AUTO
final Class javaType = context.getIdType();
if ( UUID.class.isAssignableFrom( javaType ) ) {
return UUIDGenerator.class.getName();
}
else {
return "native";
}
}
}
}
}
private static class FallbackInterpreter implements IdGenerationTypeInterpreter {
/**
* Singleton access
*/
public static final FallbackInterpreter INSTANCE = new FallbackInterpreter();
@Override
public String determineGeneratorName(GenerationType generationType, Context context) {
switch ( generationType ) {
case IDENTITY: {
return "identity";
}
case SEQUENCE: {
return org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName();
}
case TABLE: {
return org.hibernate.id.enhanced.TableGenerator.class.getName();
}
default: {
// AUTO
final Class javaType = context.getIdType();
if ( UUID.class.isAssignableFrom( javaType ) ) {
return UUIDGenerator.class.getName();
}
else {
return org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName();
}
}
}
}
}
}

View File

@ -49,6 +49,7 @@ import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService; import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService;
import org.hibernate.boot.cfgxml.spi.LoadedConfig; import org.hibernate.boot.cfgxml.spi.LoadedConfig;
import org.hibernate.boot.cfgxml.spi.MappingReference; import org.hibernate.boot.cfgxml.spi.MappingReference;
import org.hibernate.boot.model.IdGenerationTypeInterpreter;
import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.TypeContributor; import org.hibernate.boot.model.TypeContributor;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy; import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
@ -232,12 +233,6 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
return this; return this;
} }
@Override
public MetadataBuilder enableNewIdentifierGeneratorSupport(boolean enabled) {
this.options.useNewIdentifierGenerators = enabled;
return this;
}
@Override @Override
public MetadataBuilder enableExplicitDiscriminatorsForJoinedSubclassSupport(boolean supported) { public MetadataBuilder enableExplicitDiscriminatorsForJoinedSubclassSupport(boolean supported) {
options.explicitDiscriminatorsForJoinedInheritanceSupported = supported; options.explicitDiscriminatorsForJoinedInheritanceSupported = supported;
@ -383,6 +378,23 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
return this; return this;
} }
@Override
public MetadataBuilder enableNewIdentifierGeneratorSupport(boolean enabled) {
this.options.useNewIdentifierGenerators = enabled;
if ( enabled ) {
this.options.idGenerationTypeInterpreter.disableLegacyFallback();
}
else {
this.options.idGenerationTypeInterpreter.enableLegacyFallback();
}
return this;
}
@Override
public MetadataBuilder applyIdGenerationTypeInterpreter(IdGenerationTypeInterpreter interpreter) {
this.options.idGenerationTypeInterpreter.addInterpreterDelegate( interpreter );
return this;
}
// public MetadataBuilder with(PersistentAttributeMemberResolver resolver) { // public MetadataBuilder with(PersistentAttributeMemberResolver resolver) {
// options.persistentAttributeMemberResolver = resolver; // options.persistentAttributeMemberResolver = resolver;
@ -531,7 +543,6 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
private SharedCacheMode sharedCacheMode; private SharedCacheMode sharedCacheMode;
private AccessType defaultCacheAccessType; private AccessType defaultCacheAccessType;
private boolean useNewIdentifierGenerators;
private MultiTenancyStrategy multiTenancyStrategy; private MultiTenancyStrategy multiTenancyStrategy;
private ArrayList<CacheRegionDefinition> cacheRegionDefinitions; private ArrayList<CacheRegionDefinition> cacheRegionDefinitions;
private boolean explicitDiscriminatorsForJoinedInheritanceSupported; private boolean explicitDiscriminatorsForJoinedInheritanceSupported;
@ -545,6 +556,9 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
private ArrayList<AuxiliaryDatabaseObject> auxiliaryDatabaseObjectList; private ArrayList<AuxiliaryDatabaseObject> auxiliaryDatabaseObjectList;
private HashMap<Class,AttributeConverterDefinition> attributeConverterDefinitionsByClass; private HashMap<Class,AttributeConverterDefinition> attributeConverterDefinitionsByClass;
private boolean useNewIdentifierGenerators;
private IdGenerationTypeInterpreterImpl idGenerationTypeInterpreter = new IdGenerationTypeInterpreterImpl();
private static ReflectionManager generateDefaultReflectionManager() { private static ReflectionManager generateDefaultReflectionManager() {
final JavaReflectionManager reflectionManager = new JavaReflectionManager(); final JavaReflectionManager reflectionManager = new JavaReflectionManager();
reflectionManager.setMetadataProvider( new JPAMetadataProvider() ); reflectionManager.setMetadataProvider( new JPAMetadataProvider() );
@ -580,12 +594,6 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
configService.getSettings().get( AvailableSettings.SCANNER_ARCHIVE_INTERPRETER ) configService.getSettings().get( AvailableSettings.SCANNER_ARCHIVE_INTERPRETER )
); );
useNewIdentifierGenerators = configService.getSetting(
AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS,
StandardConverters.BOOLEAN,
false
);
multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configService.getSettings() ); multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configService.getSettings() );
implicitDiscriminatorsForJoinedInheritanceSupported = configService.getSetting( implicitDiscriminatorsForJoinedInheritanceSupported = configService.getSetting(
@ -670,6 +678,18 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
); );
sourceProcessOrdering = resolveInitialSourceProcessOrdering( configService ); sourceProcessOrdering = resolveInitialSourceProcessOrdering( configService );
useNewIdentifierGenerators = configService.getSetting(
AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS,
StandardConverters.BOOLEAN,
false
);
if ( useNewIdentifierGenerators ) {
idGenerationTypeInterpreter.disableLegacyFallback();
}
else {
idGenerationTypeInterpreter.enableLegacyFallback();
}
} }
private ArrayList<MetadataSourceType> resolveInitialSourceProcessOrdering(ConfigurationService configService) { private ArrayList<MetadataSourceType> resolveInitialSourceProcessOrdering(ConfigurationService configService) {
@ -764,14 +784,19 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
return defaultCacheAccessType; return defaultCacheAccessType;
} }
@Override
public MultiTenancyStrategy getMultiTenancyStrategy() {
return multiTenancyStrategy;
}
@Override @Override
public boolean isUseNewIdentifierGenerators() { public boolean isUseNewIdentifierGenerators() {
return useNewIdentifierGenerators; return useNewIdentifierGenerators;
} }
@Override @Override
public MultiTenancyStrategy getMultiTenancyStrategy() { public IdGenerationTypeInterpreter getIdGenerationTypeInterpreter() {
return multiTenancyStrategy; return idGenerationTypeInterpreter;
} }
@Override @Override

View File

@ -0,0 +1,48 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, 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.boot.model;
import javax.persistence.GenerationType;
/**
* Delegate for interpreting the name of the IdentifierGenerator to use based on
* GenerationType.
*
* @author Steve Ebersole
*/
public interface IdGenerationTypeInterpreter {
public static interface Context {
public Class getIdType();
}
/**
* Determine the name of the generator which should be used, returning {@code null} to
* indicate that this interpreter did not have a match and that any additional resolutions
* should be performed.
*
* @param generationType The {@link javax.persistence.GeneratedValue#strategy} value
* @param context The context for resolution (method parameter object)
*/
String determineGeneratorName(GenerationType generationType, Context context);
}

View File

@ -33,6 +33,7 @@ import org.hibernate.boot.CacheRegionDefinition;
import org.hibernate.boot.archive.scan.spi.ScanEnvironment; import org.hibernate.boot.archive.scan.spi.ScanEnvironment;
import org.hibernate.boot.archive.scan.spi.ScanOptions; import org.hibernate.boot.archive.scan.spi.ScanOptions;
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory; import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
import org.hibernate.boot.model.IdGenerationTypeInterpreter;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy; import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy; import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject; import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
@ -147,6 +148,13 @@ public interface MetadataBuildingOptions {
*/ */
AccessType getImplicitCacheAccessType(); AccessType getImplicitCacheAccessType();
/**
* Access to the MultiTenancyStrategy for this environment.
*
* @return The MultiTenancyStrategy
*/
MultiTenancyStrategy getMultiTenancyStrategy();
/** /**
* Access to whether we should be using the new identifier generator scheme. * Access to whether we should be using the new identifier generator scheme.
* {@code true} indicates to use the new schema, {@code false} indicates to use the * {@code true} indicates to use the new schema, {@code false} indicates to use the
@ -156,12 +164,7 @@ public interface MetadataBuildingOptions {
*/ */
boolean isUseNewIdentifierGenerators(); boolean isUseNewIdentifierGenerators();
/** IdGenerationTypeInterpreter getIdGenerationTypeInterpreter();
* Access to the MultiTenancyStrategy for this environment.
*
* @return The MultiTenancyStrategy
*/
MultiTenancyStrategy getMultiTenancyStrategy();
/** /**
* Access to all explicit cache region mappings. * Access to all explicit cache region mappings.

View File

@ -145,6 +145,7 @@ import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XMethod; import org.hibernate.annotations.common.reflection.XMethod;
import org.hibernate.annotations.common.reflection.XPackage; import org.hibernate.annotations.common.reflection.XPackage;
import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.model.IdGenerationTypeInterpreter;
import org.hibernate.boot.model.IdentifierGeneratorDefinition; import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.TypeDefinition; import org.hibernate.boot.model.TypeDefinition;
import org.hibernate.boot.spi.InFlightMetadataCollector.EntityTableXref; import org.hibernate.boot.spi.InFlightMetadataCollector.EntityTableXref;
@ -3231,38 +3232,23 @@ public final class AnnotationBinder {
private static String generatorType( private static String generatorType(
GenerationType generatorEnum, GenerationType generatorEnum,
MetadataBuildingContext buildingContext, final MetadataBuildingContext buildingContext,
XClass javaTypeXClass) { final XClass javaTypeXClass) {
boolean useNewGeneratorMappings = buildingContext.getBuildingOptions().isUseNewIdentifierGenerators(); return buildingContext.getBuildingOptions().getIdGenerationTypeInterpreter().determineGeneratorName(
switch ( generatorEnum ) { generatorEnum,
case IDENTITY: { new IdGenerationTypeInterpreter.Context() {
return "identity"; Class javaType = null;
} @Override
case AUTO: { public Class getIdType() {
final Class javaType = buildingContext.getBuildingOptions() if ( javaType == null ) {
.getReflectionManager() javaType = buildingContext.getBuildingOptions()
.toClass( javaTypeXClass ); .getReflectionManager()
if ( UUID.class.isAssignableFrom( javaType ) ) { .toClass( javaTypeXClass );
return UUIDGenerator.class.getName(); }
return javaType;
}
} }
else { );
return useNewGeneratorMappings
? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()
: "native";
}
}
case TABLE: {
return useNewGeneratorMappings
? org.hibernate.id.enhanced.TableGenerator.class.getName()
: MultipleHiLoPerTableGenerator.class.getName();
}
case SEQUENCE: {
return useNewGeneratorMappings
? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()
: "seqhilo";
}
}
throw new AssertionFailure( "Unknown GeneratorType: " + generatorEnum );
} }
private static EnumSet<CascadeType> convertToHibernateCascadeType(javax.persistence.CascadeType[] ejbCascades) { private static EnumSet<CascadeType> convertToHibernateCascadeType(javax.persistence.CascadeType[] ejbCascades) {