HHH-18524 Fix binding of meta-annotated id generators for id-class
This commit is contained in:
parent
049b76c2d1
commit
c85efaa7d2
|
@ -28,7 +28,6 @@ import org.hibernate.boot.spi.AccessType;
|
|||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.boot.spi.PropertyData;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.mapping.AggregateColumn;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
|
@ -66,19 +65,15 @@ import static org.hibernate.boot.model.internal.BinderHelper.getPath;
|
|||
import static org.hibernate.boot.model.internal.BinderHelper.getPropertyOverriddenByMapperOrMapsId;
|
||||
import static org.hibernate.boot.model.internal.BinderHelper.getRelativePath;
|
||||
import static org.hibernate.boot.model.internal.BinderHelper.hasToOneAnnotation;
|
||||
import static org.hibernate.boot.model.internal.BinderHelper.isGlobalGeneratorNameGlobal;
|
||||
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
|
||||
import static org.hibernate.boot.model.internal.GeneratorBinder.generatorType;
|
||||
import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator;
|
||||
import static org.hibernate.boot.model.internal.HCANNHelper.findContainingAnnotations;
|
||||
import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass;
|
||||
import static org.hibernate.boot.model.internal.PropertyBinder.processElementAnnotations;
|
||||
import static org.hibernate.boot.model.internal.PropertyBinder.processId;
|
||||
import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder;
|
||||
import static org.hibernate.internal.CoreLogging.messageLogger;
|
||||
import static org.hibernate.internal.util.StringHelper.isEmpty;
|
||||
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||
import static org.hibernate.internal.util.StringHelper.unqualify;
|
||||
import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY;
|
||||
|
||||
/**
|
||||
* A binder responsible for interpreting {@link Embeddable} classes and producing
|
||||
|
@ -452,18 +447,27 @@ public class EmbeddableBinder {
|
|||
inheritanceStatePerClass
|
||||
);
|
||||
|
||||
final XProperty property = propertyAnnotatedElement.getProperty();
|
||||
if ( property.isAnnotationPresent( GeneratedValue.class ) ) {
|
||||
if ( isIdClass || subholder.isOrWithinEmbeddedId() ) {
|
||||
processGeneratedId( context, component, property );
|
||||
}
|
||||
else {
|
||||
throw new AnnotationException(
|
||||
"Property '" + property.getName() + "' of '"
|
||||
+ getPath( propertyHolder, inferredData )
|
||||
+ "' is annotated '@GeneratedValue' but is not part of an identifier" );
|
||||
final XProperty member = propertyAnnotatedElement.getProperty();
|
||||
if ( isIdClass || subholder.isOrWithinEmbeddedId() ) {
|
||||
final Property property = findProperty( component, member.getName() );
|
||||
if ( property != null ) {
|
||||
// Identifier properties are always simple values
|
||||
final SimpleValue value = (SimpleValue) property.getValue();
|
||||
processId(
|
||||
subholder,
|
||||
propertyAnnotatedElement,
|
||||
value,
|
||||
Map.of(),
|
||||
context
|
||||
);
|
||||
}
|
||||
}
|
||||
else if ( member.isAnnotationPresent( GeneratedValue.class ) ) {
|
||||
throw new AnnotationException(
|
||||
"Property '" + member.getName() + "' of '"
|
||||
+ getPath( propertyHolder, inferredData )
|
||||
+ "' is annotated '@GeneratedValue' but is not part of an identifier" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( compositeUserType != null ) {
|
||||
|
@ -473,6 +477,15 @@ public class EmbeddableBinder {
|
|||
return component;
|
||||
}
|
||||
|
||||
private static Property findProperty(Component component, String name) {
|
||||
for ( Property property : component.getProperties() ) {
|
||||
if ( property.getName().equals( name ) ) {
|
||||
return property;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static CompositeUserType<?> compositeUserType(
|
||||
Class<? extends CompositeUserType<?>> compositeUserTypeClass,
|
||||
MetadataBuildingContext context) {
|
||||
|
@ -782,40 +795,6 @@ public class EmbeddableBinder {
|
|||
|| property.isAnnotationPresent(ManyToMany.class);
|
||||
}
|
||||
|
||||
private static void processGeneratedId(MetadataBuildingContext context, Component component, XProperty property) {
|
||||
final GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
|
||||
final String generatorType = generatedValue != null
|
||||
? generatorType( generatedValue, property.getType(), context )
|
||||
: DEFAULT_ID_GEN_STRATEGY;
|
||||
final String generator = generatedValue != null ? generatedValue.generator() : "";
|
||||
|
||||
if ( isGlobalGeneratorNameGlobal( context ) ) {
|
||||
buildGenerators( property, context );
|
||||
context.getMetadataCollector().addSecondPass( new IdGeneratorResolverSecondPass(
|
||||
(SimpleValue) component.getProperty( property.getName() ).getValue(),
|
||||
property,
|
||||
generatorType,
|
||||
generator,
|
||||
context
|
||||
) );
|
||||
|
||||
// handleTypeDescriptorRegistrations( property, context );
|
||||
// bindEmbeddableInstantiatorRegistrations( property, context );
|
||||
// bindCompositeUserTypeRegistrations( property, context );
|
||||
// handleConverterRegistrations( property, context );
|
||||
}
|
||||
else {
|
||||
makeIdGenerator(
|
||||
(SimpleValue) component.getProperty( property.getName() ).getValue(),
|
||||
property,
|
||||
generatorType,
|
||||
generator,
|
||||
context,
|
||||
new HashMap<>( buildGenerators( property, context ) )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void processIdClassElements(
|
||||
PropertyHolder propertyHolder,
|
||||
PropertyData baseInferredData,
|
||||
|
|
|
@ -59,6 +59,7 @@ import jakarta.persistence.Version;
|
|||
import static org.hibernate.boot.model.internal.BinderHelper.isCompositeId;
|
||||
import static org.hibernate.boot.model.internal.BinderHelper.isGlobalGeneratorNameGlobal;
|
||||
import static org.hibernate.id.factory.internal.IdentifierGeneratorUtil.collectParameters;
|
||||
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
|
||||
import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY;
|
||||
|
||||
public class GeneratorBinder {
|
||||
|
@ -113,16 +114,10 @@ public class GeneratorBinder {
|
|||
|| identifierGeneratorStrategy.equals( "seqhilo" );
|
||||
if ( generatorType == null || !avoidOverriding ) {
|
||||
id.setIdentifierGeneratorStrategy( identifierGeneratorStrategy );
|
||||
if ( DEFAULT_ID_GEN_STRATEGY.equals( identifierGeneratorStrategy ) ) {
|
||||
id.setNullValue( "undefined" );
|
||||
}
|
||||
}
|
||||
//checkIfMatchingGenerator(definition, generatorType, generatorName);
|
||||
parameters.putAll( definition.getParameters() );
|
||||
}
|
||||
if ( DEFAULT_ID_GEN_STRATEGY.equals( generatorType ) ) {
|
||||
id.setNullValue( "undefined" );
|
||||
}
|
||||
id.setIdentifierGeneratorParameters( parameters );
|
||||
}
|
||||
|
||||
|
@ -564,9 +559,9 @@ public class GeneratorBinder {
|
|||
XProperty idProperty) {
|
||||
//manage composite related metadata
|
||||
//guess if its a component and find id data access (property, field etc)
|
||||
final GeneratedValue generatedValue = idProperty.getAnnotation( GeneratedValue.class );
|
||||
final GeneratedValue generatedValue = castNonNull( idProperty.getAnnotation( GeneratedValue.class ) );
|
||||
final String generatorType = generatorType( context, entityClass, isCompositeId( entityClass, idProperty ), generatedValue );
|
||||
final String generatorName = generatedValue == null ? "" : generatedValue.generator();
|
||||
final String generatorName = generatedValue.generator();
|
||||
if ( isGlobalGeneratorNameGlobal( context ) ) {
|
||||
buildGenerators( idProperty, context );
|
||||
context.getMetadataCollector().addSecondPass( new IdGeneratorResolverSecondPass(
|
||||
|
|
|
@ -15,6 +15,7 @@ import jakarta.persistence.Basic;
|
|||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.ElementCollection;
|
||||
import jakarta.persistence.EmbeddedId;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
|
@ -1156,13 +1157,16 @@ public class PropertyBinder {
|
|||
);
|
||||
}
|
||||
else if ( propertyBinder.isId() ) {
|
||||
if ( isIdentifierMapper ) {
|
||||
throw new AnnotationException( "Property '"+ getPath( propertyHolder, inferredData )
|
||||
+ "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" );
|
||||
}
|
||||
//components and regular basic types create SimpleValue objects
|
||||
processId(
|
||||
propertyHolder,
|
||||
inferredData,
|
||||
(SimpleValue) propertyBinder.getValue(),
|
||||
classGenerators,
|
||||
isIdentifierMapper,
|
||||
context
|
||||
);
|
||||
}
|
||||
|
@ -1415,17 +1419,12 @@ public class PropertyBinder {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static void processId(
|
||||
static void processId(
|
||||
PropertyHolder propertyHolder,
|
||||
PropertyData inferredData,
|
||||
SimpleValue idValue,
|
||||
Map<String, IdentifierGeneratorDefinition> classGenerators,
|
||||
boolean isIdentifierMapper,
|
||||
MetadataBuildingContext context) {
|
||||
if ( isIdentifierMapper ) {
|
||||
throw new AnnotationException( "Property '"+ getPath( propertyHolder, inferredData )
|
||||
+ "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" );
|
||||
}
|
||||
final XProperty idProperty = inferredData.getProperty();
|
||||
final List<Annotation> idGeneratorAnnotations = findContainingAnnotations( idProperty, IdGeneratorType.class );
|
||||
final List<Annotation> generatorAnnotations = findContainingAnnotations( idProperty, ValueGenerationType.class );
|
||||
|
@ -1449,7 +1448,7 @@ public class PropertyBinder {
|
|||
+ "' is annotated '" + generatorAnnotations.get(0).annotationType()
|
||||
+ "' which is not an '@IdGeneratorType'" );
|
||||
}
|
||||
else {
|
||||
else if ( idProperty.isAnnotationPresent( GeneratedValue.class ) ) {
|
||||
final XClass entityClass = inferredData.getClassOrElement();
|
||||
createIdGenerator( idValue, classGenerators, context, entityClass, idProperty );
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
|
|
|
@ -43,4 +43,9 @@ public class Assigned implements IdentifierGenerator, StandardGenerator {
|
|||
throw new MappingException("no entity name");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowAssignedIdentifiers() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ import org.hibernate.integrator.spi.IntegratorService;
|
|||
import org.hibernate.jpa.internal.ExceptionMapperLegacyJpaImpl;
|
||||
import org.hibernate.jpa.internal.PersistenceUnitUtilImpl;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.KeyValue;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
import org.hibernate.mapping.SimpleValue;
|
||||
|
@ -462,7 +463,8 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
|
|||
bootMetamodel.getEntityBindings().stream()
|
||||
.filter( model -> !model.isInherited() )
|
||||
.forEach( model -> {
|
||||
final Generator generator = model.getIdentifier().createGenerator(
|
||||
final KeyValue id = model.getIdentifier();
|
||||
final Generator generator = id.createGenerator(
|
||||
bootstrapContext.getIdentifierGeneratorFactory(),
|
||||
jdbcServices.getJdbcEnvironment().getDialect(),
|
||||
(RootClass) model
|
||||
|
@ -471,8 +473,11 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
|
|||
final Configurable identifierGenerator = (Configurable) generator;
|
||||
identifierGenerator.initialize( sqlStringGenerationContext );
|
||||
}
|
||||
if ( generator.allowAssignedIdentifiers() ) {
|
||||
( (SimpleValue) model.getIdentifier() ).setNullValue( "undefined" );
|
||||
if ( generator.allowAssignedIdentifiers() && id instanceof SimpleValue ) {
|
||||
final SimpleValue simpleValue = (SimpleValue) id;
|
||||
if ( simpleValue.getNullValue() == null ) {
|
||||
simpleValue.setNullValue( "undefined" );
|
||||
}
|
||||
}
|
||||
generators.put( model.getEntityName(), generator );
|
||||
} );
|
||||
|
|
|
@ -719,7 +719,8 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
|
|||
if ( property.getValue().isSimpleValue() ) {
|
||||
final SimpleValue value = (SimpleValue) property.getValue();
|
||||
|
||||
if ( !DEFAULT_ID_GEN_STRATEGY.equals( value.getIdentifierGeneratorStrategy() ) ) {
|
||||
if ( !DEFAULT_ID_GEN_STRATEGY.equals( value.getIdentifierGeneratorStrategy() )
|
||||
|| value.getCustomIdGeneratorCreator() != null ) {
|
||||
// skip any 'assigned' generators, they would have been handled by
|
||||
// the StandardGenerationContextLocator
|
||||
generator.addGeneratedValuePlan( new ValueGenerationPlan(
|
||||
|
|
Loading…
Reference in New Issue