10
10
import java .util .List ;
11
11
import java .util .Map ;
12
12
13
+ import jakarta .persistence .GeneratedValue ;
13
14
import jakarta .persistence .MapKey ;
14
15
import jakarta .persistence .MapKeyClass ;
15
16
import jakarta .persistence .MapKeyColumn ;
25
26
import org .hibernate .annotations .Any ;
26
27
import org .hibernate .annotations .AttributeBinderType ;
27
28
import org .hibernate .annotations .CompositeType ;
29
+ import org .hibernate .annotations .IdGeneratorType ;
28
30
import org .hibernate .annotations .Immutable ;
29
31
import org .hibernate .annotations .LazyGroup ;
30
32
import org .hibernate .annotations .ManyToAny ;
@@ -596,20 +598,22 @@ private static int addProperty(
596
598
List <PropertyData > inFlightPropertyDataList ,
597
599
MetadataBuildingContext context ,
598
600
int idPropertyCounter ) {
601
+ final InFlightMetadataCollector collector = context .getMetadataCollector ();
602
+
599
603
// see if inFlightPropertyDataList already contains a PropertyData for this name,
600
604
// and if so, skip it...
601
605
for ( PropertyData propertyData : inFlightPropertyDataList ) {
602
606
if ( propertyData .getPropertyName ().equals ( property .resolveAttributeName () ) ) {
603
- checkIdProperty ( property , propertyData );
607
+ checkIdProperty ( property , propertyData , collector . getSourceModelBuildingContext () );
604
608
// EARLY EXIT!!!
605
609
return idPropertyCounter ;
606
610
}
607
611
}
608
612
609
- final ClassDetails declaringClass = propertyContainer .getDeclaringClass ();
610
613
final TypeVariableScope ownerType = propertyContainer .getTypeAtStake ();
614
+
611
615
final PropertyData propertyAnnotatedElement = new PropertyInferredData (
612
- declaringClass ,
616
+ propertyContainer . getDeclaringClass () ,
613
617
ownerType ,
614
618
property ,
615
619
propertyContainer .getClassLevelAccessType ().getType (),
@@ -622,31 +626,51 @@ private static int addProperty(
622
626
if ( hasIdAnnotation ( element ) ) {
623
627
inFlightPropertyDataList .add ( idPropertyCounter , propertyAnnotatedElement );
624
628
if ( hasToOneAnnotation ( element ) ) {
625
- context .getMetadataCollector ()
626
- .addToOneAndIdProperty ( ownerType .determineRawClass (), propertyAnnotatedElement );
629
+ collector .addToOneAndIdProperty ( ownerType .determineRawClass (), propertyAnnotatedElement );
627
630
}
628
631
idPropertyCounter ++;
629
632
}
630
633
else {
631
634
inFlightPropertyDataList .add ( propertyAnnotatedElement );
632
635
}
633
636
if ( element .hasDirectAnnotationUsage ( MapsId .class ) ) {
634
- context .getMetadataCollector ()
635
- .addPropertyAnnotatedWithMapsId ( ownerType .determineRawClass (), propertyAnnotatedElement );
637
+ collector .addPropertyAnnotatedWithMapsId ( ownerType .determineRawClass (), propertyAnnotatedElement );
636
638
}
637
639
638
640
return idPropertyCounter ;
639
641
}
640
642
641
- private static void checkIdProperty (MemberDetails property , PropertyData propertyData ) {
642
- final Id incomingIdProperty = property . getDirectAnnotationUsage ( Id . class );
643
+ private static void checkIdProperty (MemberDetails property , PropertyData propertyData , SourceModelBuildingContext context ) {
644
+ final boolean incomingIdProperty = hasIdAnnotation ( property );
643
645
final MemberDetails attributeMember = propertyData .getAttributeMember ();
644
- final Id existingIdProperty = attributeMember .getDirectAnnotationUsage ( Id .class );
645
- if ( incomingIdProperty != null && existingIdProperty == null ) {
646
- throw new MappingException (
647
- "Attribute '" + attributeMember .getName ()
648
- + "' is declared by '" + attributeMember .getDeclaringType ().getName ()
649
- + "' and may not be redeclared as an '@Id' by '" + property .getDeclaringType ().getName () + "'" );
646
+ final boolean existingIdProperty = hasIdAnnotation ( attributeMember );
647
+ if ( incomingIdProperty ) {
648
+ if ( existingIdProperty ) {
649
+ if ( property .hasDirectAnnotationUsage ( GeneratedValue .class )
650
+ || !property .getMetaAnnotated ( IdGeneratorType .class , context ).isEmpty () ) {
651
+ //TODO: it would be nice to allow a root @Entity to override an
652
+ // @Id field declared by a @MappedSuperclass and change the
653
+ // generator, but for now we don't seem to be able to detect
654
+ // that case here
655
+ throw new AnnotationException (
656
+ "Attribute '" + attributeMember .getName ()
657
+ + "' is declared as an '@Id' or '@EmbeddedId' property by '"
658
+ + attributeMember .getDeclaringType ().getName ()
659
+ + "' and so '" + property .getDeclaringType ().getName ()
660
+ + "' may not respecify the generation strategy" );
661
+ }
662
+ }
663
+ else {
664
+ //TODO: it would be nice to allow a root @Entity to override a
665
+ // field declared by a @MappedSuperclass, redeclaring it
666
+ // as an @Id field, but for now we don't seem to be able
667
+ // to detect that case here
668
+ throw new AnnotationException (
669
+ "Attribute '" + attributeMember .getName ()
670
+ + "' is declared by '" + attributeMember .getDeclaringType ().getName ()
671
+ + "' and may not be redeclared as an '@Id' or '@EmbeddedId' by '"
672
+ + property .getDeclaringType ().getName () + "'" );
673
+ }
650
674
}
651
675
}
652
676
@@ -721,14 +745,17 @@ private static void buildProperty(
721
745
MetadataBuildingContext context ,
722
746
Map <ClassDetails , InheritanceState > inheritanceStatePerClass ,
723
747
MemberDetails property ) {
748
+
749
+ if ( isPropertyOfRegularEmbeddable ( propertyHolder , isComponentEmbedded )
750
+ && property .hasDirectAnnotationUsage (Id .class )) {
751
+ throw new AnnotationException ("Member '" + property .getName ()
752
+ + "' of embeddable class " + propertyHolder .getClassName () + " is annotated '@Id'" );
753
+ }
754
+
724
755
final TypeDetails attributeTypeDetails =
725
756
inferredData .getAttributeMember ().isPlural ()
726
757
? inferredData .getAttributeMember ().getType ()
727
758
: inferredData .getClassOrElementType ();
728
- final ClassDetails attributeClassDetails = attributeTypeDetails .determineRawClass ();
729
- final ColumnsBuilder columnsBuilder =
730
- new ColumnsBuilder ( propertyHolder , nullability , property , inferredData , entityBinder , context )
731
- .extractMetadata ();
732
759
733
760
final PropertyBinder propertyBinder = propertyBinder (
734
761
propertyHolder ,
@@ -741,17 +768,14 @@ private static void buildProperty(
741
768
attributeTypeDetails
742
769
);
743
770
744
- if ( isPropertyOfRegularEmbeddable ( propertyHolder , isComponentEmbedded )
745
- && property .hasDirectAnnotationUsage (Id .class )) {
746
- throw new AnnotationException ("Member '" + property .getName ()
747
- + "' of embeddable class " + propertyHolder .getClassName () + " is annotated '@Id'" );
748
- }
749
-
750
771
final LazyGroup lazyGroupAnnotation = property .getDirectAnnotationUsage ( LazyGroup .class );
751
772
if ( lazyGroupAnnotation != null ) {
752
773
propertyBinder .setLazyGroup ( lazyGroupAnnotation .value () );
753
774
}
754
775
776
+ final ColumnsBuilder columnsBuilder =
777
+ new ColumnsBuilder ( propertyHolder , nullability , property , inferredData , entityBinder , context )
778
+ .extractMetadata ();
755
779
final AnnotatedJoinColumns joinColumns = columnsBuilder .getJoinColumns ();
756
780
final AnnotatedColumns columns = propertyBinder .bindProperty (
757
781
propertyHolder ,
@@ -762,7 +786,7 @@ private static void buildProperty(
762
786
isComponentEmbedded ,
763
787
inSecondPass ,
764
788
property ,
765
- attributeClassDetails ,
789
+ attributeTypeDetails . determineRawClass () ,
766
790
columnsBuilder
767
791
);
768
792
addNaturalIds ( inSecondPass , property , columns , joinColumns , context );
0 commit comments