Skip to content

Commit d0c3aa4

Browse files
committed
HHH-19688 fix for @IdClass with a single @manytoone or @OnetoOne
1 parent 89d7ee0 commit d0c3aa4

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

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

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -648,23 +648,19 @@ private boolean isIdClassPrimaryKeyOfAssociatedEntity(
648648
// entity referenced via a @ManyToOne or @OneToOne association
649649
final PropertyData idPropertyOnBaseClass =
650650
getUniqueIdPropertyFromBaseClass( inferredData, baseInferredData, propertyAccessor, context );
651-
final InheritanceState state =
652-
inheritanceStates.get( idPropertyOnBaseClass.getClassOrElementType().determineRawClass() );
651+
final TypeDetails idPropertyType = idPropertyOnBaseClass.getClassOrElementType();
652+
final InheritanceState state = inheritanceStates.get( idPropertyType.determineRawClass() );
653653
if ( state == null ) {
654654
// Likely a user error, but treat it as something that might happen
655655
return false;
656656
}
657657
else {
658658
final ClassDetails associatedClassWithIdClass = state.getClassWithIdClass( true );
659659
if ( associatedClassWithIdClass == null ) {
660-
// We cannot know for sure here without looking at the identifier
661-
// type of the associated entity. Instead of doing that, we look to
662-
// see if our @Id field has a @ManyToOne or @OneToOne annotation,
663-
// making the possibly wrong assumption that an @Id @ManyToOne or
664-
// @Id @OneToOne always has the type of the associated entity, and
665-
// is never a different @IdClass with a single field just holding
666-
// the PK of the associated entity.
667-
return hasToOneAnnotation( idPropertyOnBaseClass.getAttributeMember() );
660+
// If annotated @OneToOne or @ManyToOne, it's an association to another entity
661+
return hasToOneAnnotation( idPropertyOnBaseClass.getAttributeMember() )
662+
// determine if the @Id or @EmbeddedId tpe is the same
663+
&& isIdClassOfAssociatedEntity( compositeClass, propertyAccessor, context, idPropertyType );
668664
}
669665
else {
670666
// The associated entity has an @IdClass, so check if it's the same
@@ -681,6 +677,29 @@ private boolean isIdClassPrimaryKeyOfAssociatedEntity(
681677
}
682678
}
683679

680+
private static boolean isIdClassOfAssociatedEntity(
681+
ClassDetails compositeClass,
682+
AccessType propertyAccessor,
683+
MetadataBuildingContext context,
684+
TypeDetails idPropertyType) {
685+
// Determine the @Id type or @EmbeddedId class of the associated entity
686+
final var propertyContainer =
687+
new PropertyContainer( idPropertyType.determineRawClass(), idPropertyType, propertyAccessor );
688+
final List<PropertyData> idProperties = new ArrayList<>();
689+
final int idPropertyCount = addElementsOfClass( idProperties, propertyContainer, context, 0 );
690+
if ( idPropertyCount == 1 ) {
691+
// Exactly one @Id or @EmbeddedId attribute
692+
final PropertyData idPropertyOfAssociatedEntity = idProperties.get( 0 );
693+
return compositeClass.getName()
694+
.equals( idPropertyOfAssociatedEntity.getPropertyType().getName() );
695+
}
696+
else {
697+
// No id property found in the associated class,
698+
// or multiple id properties but no @IdClass
699+
return false;
700+
}
701+
}
702+
684703
private Component bindIdClass(
685704
PropertyData inferredData,
686705
PropertyData baseInferredData,

0 commit comments

Comments
 (0)