Skip to content

Commit b8b8f01

Browse files
committed
HHH-18524 Fix binding of meta-annotated id generators for id-class
1 parent 6d0c959 commit b8b8f01

File tree

5 files changed

+59
-52
lines changed

5 files changed

+59
-52
lines changed

hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java

Lines changed: 30 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,8 @@
6666
import static org.hibernate.boot.model.internal.BinderHelper.getPropertyOverriddenByMapperOrMapsId;
6767
import static org.hibernate.boot.model.internal.BinderHelper.getRelativePath;
6868
import static org.hibernate.boot.model.internal.BinderHelper.hasToOneAnnotation;
69-
import static org.hibernate.boot.model.internal.BinderHelper.isGlobalGeneratorNameGlobal;
7069
import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverridableAnnotation;
71-
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
72-
import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator;
73-
import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorStrategy;
70+
import static org.hibernate.boot.model.internal.GeneratorBinder.createIdGeneratorsFromGeneratorAnnotations;
7471
import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass;
7572
import static org.hibernate.boot.model.internal.PropertyBinder.processElementAnnotations;
7673
import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder;
@@ -464,7 +461,7 @@ static Component fillEmbeddable(
464461
? Nullability.FORCED_NULL
465462
: ( isNullable ? Nullability.NO_CONSTRAINT : Nullability.FORCED_NOT_NULL ),
466463
propertyAnnotatedElement,
467-
new HashMap<>(),
464+
Map.of(),
468465
entityBinder,
469466
isIdentifierMapper,
470467
isComponentEmbedded,
@@ -473,18 +470,27 @@ static Component fillEmbeddable(
473470
inheritanceStatePerClass
474471
);
475472

476-
final MemberDetails property = propertyAnnotatedElement.getAttributeMember();
477-
if ( property.hasDirectAnnotationUsage( GeneratedValue.class ) ) {
478-
if ( isIdClass || subholder.isOrWithinEmbeddedId() ) {
479-
processGeneratedId( context, component, property );
480-
}
481-
else {
482-
throw new AnnotationException(
483-
"Property '" + property.getName() + "' of '"
484-
+ getPath( propertyHolder, inferredData )
485-
+ "' is annotated '@GeneratedValue' but is not part of an identifier" );
473+
final MemberDetails member = propertyAnnotatedElement.getAttributeMember();
474+
if ( isIdClass || subholder.isOrWithinEmbeddedId() ) {
475+
final Property property = findProperty( component, member.getName() );
476+
if ( property != null ) {
477+
// Identifier properties are always simple values
478+
final SimpleValue value = (SimpleValue) property.getValue();
479+
createIdGeneratorsFromGeneratorAnnotations(
480+
subholder,
481+
propertyAnnotatedElement,
482+
value,
483+
Map.of(),
484+
context
485+
);
486486
}
487487
}
488+
else if ( member.hasDirectAnnotationUsage( GeneratedValue.class ) ) {
489+
throw new AnnotationException(
490+
"Property '" + member.getName() + "' of '"
491+
+ getPath( propertyHolder, inferredData )
492+
+ "' is annotated '@GeneratedValue' but is not part of an identifier" );
493+
}
488494
}
489495

490496
if ( compositeUserType != null ) {
@@ -494,6 +500,15 @@ static Component fillEmbeddable(
494500
return component;
495501
}
496502

503+
private static Property findProperty(Component component, String name) {
504+
for ( Property property : component.getProperties() ) {
505+
if ( property.getName().equals( name ) ) {
506+
return property;
507+
}
508+
}
509+
return null;
510+
}
511+
497512
private static CompositeUserType<?> compositeUserType(
498513
Class<? extends CompositeUserType<?>> compositeUserTypeClass,
499514
MetadataBuildingContext context) {
@@ -812,40 +827,6 @@ private static boolean hasTriggeringAnnotation(MemberDetails property) {
812827
|| property.hasDirectAnnotationUsage(ManyToMany.class);
813828
}
814829

815-
private static void processGeneratedId(MetadataBuildingContext context, Component component, MemberDetails property) {
816-
final GeneratedValue generatedValue = property.getDirectAnnotationUsage( GeneratedValue.class );
817-
final String generatorType =
818-
generatorStrategy( generatedValue.strategy(), generatedValue.generator(), property.getType() );
819-
final String generator = generatedValue.generator();
820-
821-
final SimpleValue value = (SimpleValue) component.getProperty( property.getName()).getValue();
822-
if ( isGlobalGeneratorNameGlobal( context ) ) {
823-
buildGenerators( property, context );
824-
context.getMetadataCollector().addSecondPass( new IdGeneratorResolverSecondPass(
825-
value,
826-
property,
827-
generatorType,
828-
generator,
829-
context
830-
) );
831-
832-
// handleTypeDescriptorRegistrations( property, context );
833-
// bindEmbeddableInstantiatorRegistrations( property, context );
834-
// bindCompositeUserTypeRegistrations( property, context );
835-
// handleConverterRegistrations( property, context );
836-
}
837-
else {
838-
makeIdGenerator(
839-
value,
840-
property,
841-
generatorType,
842-
generator,
843-
context,
844-
new HashMap<>( buildGenerators( property, context ) )
845-
);
846-
}
847-
}
848-
849830
private static void processIdClassElements(
850831
PropertyHolder propertyHolder,
851832
PropertyData baseInferredData,

hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorBinder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import static org.hibernate.boot.model.internal.GeneratorParameters.interpretTableGenerator;
6666
import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorClass;
6767
import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorStrategy;
68+
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
6869
import static org.hibernate.internal.util.StringHelper.qualify;
6970
import static org.hibernate.resource.beans.internal.Helper.allowExtensionsInCdi;
7071

@@ -600,7 +601,7 @@ private static void createIdGenerator(
600601
MemberDetails idMember) {
601602
//manage composite related metadata
602603
//guess if its a component and find id data access (property, field etc)
603-
final GeneratedValue generatedValue = idMember.getDirectAnnotationUsage( GeneratedValue.class );
604+
final GeneratedValue generatedValue = castNonNull( idMember.getDirectAnnotationUsage( GeneratedValue.class ) );
604605
final String generatorType =
605606
generatorStrategy( generatedValue.strategy(), generatedValue.generator(), idMember.getType() );
606607
final String generatorName = generatedValue.generator();

hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1135,11 +1135,11 @@ && isEmbedded( property, property.getElementType() ) ) {
11351135
);
11361136
}
11371137
else if ( propertyBinder.isId() ) {
1138-
//components and regular basic types create SimpleValue objects
11391138
if ( isIdentifierMapper ) {
11401139
throw new AnnotationException( "Property '"+ getPath( propertyHolder, inferredData )
11411140
+ "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" );
11421141
}
1142+
//components and regular basic types create SimpleValue objects
11431143
createIdGeneratorsFromGeneratorAnnotations(
11441144
propertyHolder,
11451145
inferredData,

hibernate-core/src/test/java/org/hibernate/orm/test/tenantidpk/Account.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
import jakarta.persistence.Entity;
44
import jakarta.persistence.GeneratedValue;
55
import jakarta.persistence.Id;
6+
import jakarta.persistence.IdClass;
67
import jakarta.persistence.ManyToOne;
78
import org.hibernate.annotations.TenantId;
89

910
import java.util.UUID;
1011

11-
@Entity
12+
@Entity @IdClass(TenantizedId.class)
1213
public class Account {
1314

1415
@Id @GeneratedValue Long id;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
6+
*/
7+
package org.hibernate.orm.test.tenantidpk;
8+
9+
import java.util.UUID;
10+
11+
import jakarta.persistence.Embeddable;
12+
13+
@Embeddable
14+
public class TenantizedId {
15+
Long id;
16+
UUID tenantId;
17+
18+
public TenantizedId(Long id, UUID tenantId) {
19+
this.id = id;
20+
this.tenantId = tenantId;
21+
}
22+
23+
TenantizedId() {}
24+
}

0 commit comments

Comments
 (0)