HHH-18524 Fix binding of meta-annotated id generators for id-class
This commit is contained in:
parent
6d0c9599e6
commit
b8b8f011dc
|
@ -66,11 +66,8 @@ 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.getPropertyOverriddenByMapperOrMapsId;
|
||||||
import static org.hibernate.boot.model.internal.BinderHelper.getRelativePath;
|
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.hasToOneAnnotation;
|
||||||
import static org.hibernate.boot.model.internal.BinderHelper.isGlobalGeneratorNameGlobal;
|
|
||||||
import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverridableAnnotation;
|
import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverridableAnnotation;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
|
import static org.hibernate.boot.model.internal.GeneratorBinder.createIdGeneratorsFromGeneratorAnnotations;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator;
|
|
||||||
import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorStrategy;
|
|
||||||
import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass;
|
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.processElementAnnotations;
|
||||||
import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder;
|
import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder;
|
||||||
|
@ -464,7 +461,7 @@ public class EmbeddableBinder {
|
||||||
? Nullability.FORCED_NULL
|
? Nullability.FORCED_NULL
|
||||||
: ( isNullable ? Nullability.NO_CONSTRAINT : Nullability.FORCED_NOT_NULL ),
|
: ( isNullable ? Nullability.NO_CONSTRAINT : Nullability.FORCED_NOT_NULL ),
|
||||||
propertyAnnotatedElement,
|
propertyAnnotatedElement,
|
||||||
new HashMap<>(),
|
Map.of(),
|
||||||
entityBinder,
|
entityBinder,
|
||||||
isIdentifierMapper,
|
isIdentifierMapper,
|
||||||
isComponentEmbedded,
|
isComponentEmbedded,
|
||||||
|
@ -473,18 +470,27 @@ public class EmbeddableBinder {
|
||||||
inheritanceStatePerClass
|
inheritanceStatePerClass
|
||||||
);
|
);
|
||||||
|
|
||||||
final MemberDetails property = propertyAnnotatedElement.getAttributeMember();
|
final MemberDetails member = propertyAnnotatedElement.getAttributeMember();
|
||||||
if ( property.hasDirectAnnotationUsage( GeneratedValue.class ) ) {
|
if ( isIdClass || subholder.isOrWithinEmbeddedId() ) {
|
||||||
if ( isIdClass || subholder.isOrWithinEmbeddedId() ) {
|
final Property property = findProperty( component, member.getName() );
|
||||||
processGeneratedId( context, component, property );
|
if ( property != null ) {
|
||||||
}
|
// Identifier properties are always simple values
|
||||||
else {
|
final SimpleValue value = (SimpleValue) property.getValue();
|
||||||
throw new AnnotationException(
|
createIdGeneratorsFromGeneratorAnnotations(
|
||||||
"Property '" + property.getName() + "' of '"
|
subholder,
|
||||||
+ getPath( propertyHolder, inferredData )
|
propertyAnnotatedElement,
|
||||||
+ "' is annotated '@GeneratedValue' but is not part of an identifier" );
|
value,
|
||||||
|
Map.of(),
|
||||||
|
context
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ( member.hasDirectAnnotationUsage( 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 ) {
|
if ( compositeUserType != null ) {
|
||||||
|
@ -494,6 +500,15 @@ public class EmbeddableBinder {
|
||||||
return component;
|
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(
|
private static CompositeUserType<?> compositeUserType(
|
||||||
Class<? extends CompositeUserType<?>> compositeUserTypeClass,
|
Class<? extends CompositeUserType<?>> compositeUserTypeClass,
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
|
@ -812,40 +827,6 @@ public class EmbeddableBinder {
|
||||||
|| property.hasDirectAnnotationUsage(ManyToMany.class);
|
|| property.hasDirectAnnotationUsage(ManyToMany.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processGeneratedId(MetadataBuildingContext context, Component component, MemberDetails property) {
|
|
||||||
final GeneratedValue generatedValue = property.getDirectAnnotationUsage( GeneratedValue.class );
|
|
||||||
final String generatorType =
|
|
||||||
generatorStrategy( generatedValue.strategy(), generatedValue.generator(), property.getType() );
|
|
||||||
final String generator = generatedValue.generator();
|
|
||||||
|
|
||||||
final SimpleValue value = (SimpleValue) component.getProperty( property.getName()).getValue();
|
|
||||||
if ( isGlobalGeneratorNameGlobal( context ) ) {
|
|
||||||
buildGenerators( property, context );
|
|
||||||
context.getMetadataCollector().addSecondPass( new IdGeneratorResolverSecondPass(
|
|
||||||
value,
|
|
||||||
property,
|
|
||||||
generatorType,
|
|
||||||
generator,
|
|
||||||
context
|
|
||||||
) );
|
|
||||||
|
|
||||||
// handleTypeDescriptorRegistrations( property, context );
|
|
||||||
// bindEmbeddableInstantiatorRegistrations( property, context );
|
|
||||||
// bindCompositeUserTypeRegistrations( property, context );
|
|
||||||
// handleConverterRegistrations( property, context );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
makeIdGenerator(
|
|
||||||
value,
|
|
||||||
property,
|
|
||||||
generatorType,
|
|
||||||
generator,
|
|
||||||
context,
|
|
||||||
new HashMap<>( buildGenerators( property, context ) )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void processIdClassElements(
|
private static void processIdClassElements(
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
PropertyData baseInferredData,
|
PropertyData baseInferredData,
|
||||||
|
|
|
@ -65,6 +65,7 @@ import static org.hibernate.boot.model.internal.GeneratorParameters.interpretSeq
|
||||||
import static org.hibernate.boot.model.internal.GeneratorParameters.interpretTableGenerator;
|
import static org.hibernate.boot.model.internal.GeneratorParameters.interpretTableGenerator;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorClass;
|
import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorClass;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorStrategy;
|
import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorStrategy;
|
||||||
|
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
|
||||||
import static org.hibernate.internal.util.StringHelper.qualify;
|
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||||
import static org.hibernate.resource.beans.internal.Helper.allowExtensionsInCdi;
|
import static org.hibernate.resource.beans.internal.Helper.allowExtensionsInCdi;
|
||||||
|
|
||||||
|
@ -600,7 +601,7 @@ public class GeneratorBinder {
|
||||||
MemberDetails idMember) {
|
MemberDetails idMember) {
|
||||||
//manage composite related metadata
|
//manage composite related metadata
|
||||||
//guess if its a component and find id data access (property, field etc)
|
//guess if its a component and find id data access (property, field etc)
|
||||||
final GeneratedValue generatedValue = idMember.getDirectAnnotationUsage( GeneratedValue.class );
|
final GeneratedValue generatedValue = castNonNull( idMember.getDirectAnnotationUsage( GeneratedValue.class ) );
|
||||||
final String generatorType =
|
final String generatorType =
|
||||||
generatorStrategy( generatedValue.strategy(), generatedValue.generator(), idMember.getType() );
|
generatorStrategy( generatedValue.strategy(), generatedValue.generator(), idMember.getType() );
|
||||||
final String generatorName = generatedValue.generator();
|
final String generatorName = generatedValue.generator();
|
||||||
|
|
|
@ -1135,11 +1135,11 @@ public class PropertyBinder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if ( propertyBinder.isId() ) {
|
else if ( propertyBinder.isId() ) {
|
||||||
//components and regular basic types create SimpleValue objects
|
|
||||||
if ( isIdentifierMapper ) {
|
if ( isIdentifierMapper ) {
|
||||||
throw new AnnotationException( "Property '"+ getPath( propertyHolder, inferredData )
|
throw new AnnotationException( "Property '"+ getPath( propertyHolder, inferredData )
|
||||||
+ "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" );
|
+ "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" );
|
||||||
}
|
}
|
||||||
|
//components and regular basic types create SimpleValue objects
|
||||||
createIdGeneratorsFromGeneratorAnnotations(
|
createIdGeneratorsFromGeneratorAnnotations(
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
inferredData,
|
inferredData,
|
||||||
|
|
|
@ -3,12 +3,13 @@ package org.hibernate.orm.test.tenantidpk;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.IdClass;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import org.hibernate.annotations.TenantId;
|
import org.hibernate.annotations.TenantId;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Entity
|
@Entity @IdClass(TenantizedId.class)
|
||||||
public class Account {
|
public class Account {
|
||||||
|
|
||||||
@Id @GeneratedValue Long id;
|
@Id @GeneratedValue Long id;
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.tenantidpk;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import jakarta.persistence.Embeddable;
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public class TenantizedId {
|
||||||
|
Long id;
|
||||||
|
UUID tenantId;
|
||||||
|
|
||||||
|
public TenantizedId(Long id, UUID tenantId) {
|
||||||
|
this.id = id;
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
TenantizedId() {}
|
||||||
|
}
|
Loading…
Reference in New Issue