Skip to content

Commit 6bf3f15

Browse files
committed
HHH-18062 Fix id-class record instantiation and mapper component
1 parent 24e0152 commit 6bf3f15

File tree

4 files changed

+72
-28
lines changed

4 files changed

+72
-28
lines changed

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ private boolean mapAsIdClass(
493493
else {
494494
final boolean ignoreIdAnnotations = isIgnoreIdAnnotations();
495495
setIgnoreIdAnnotations( true );
496-
bindIdClass(
496+
final Component idClassComponent = bindIdClass(
497497
inferredData,
498498
baseInferredData,
499499
propertyHolder,
@@ -512,6 +512,9 @@ private boolean mapAsIdClass(
512512
propertyAccessor,
513513
true
514514
);
515+
if ( idClassComponent.isSimpleRecord() ) {
516+
mapper.setSimpleRecord( true );
517+
}
515518
setIgnoreIdAnnotations( ignoreIdAnnotations );
516519
for ( Property property : mapper.getProperties() ) {
517520
idPropertiesIfIdClass.add( property.getName() );
@@ -654,7 +657,7 @@ private static boolean isIdClassPkOfTheAssociatedEntity(
654657
}
655658
}
656659

657-
private void bindIdClass(
660+
private Component bindIdClass(
658661
PropertyData inferredData,
659662
PropertyData baseInferredData,
660663
PropertyHolder propertyHolder,
@@ -705,6 +708,8 @@ private void bindIdClass(
705708
rootClass.setEmbeddedIdentifier( inferredData.getPropertyClass() == null );
706709

707710
propertyHolder.setInIdClass( null );
711+
712+
return id;
708713
}
709714

710715
private static void handleIdGenerator(PropertyData inferredData, MetadataBuildingContext buildingContext, Component id) {

hibernate-core/src/main/java/org/hibernate/mapping/Component.java

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
8989
private AggregateColumn parentAggregateColumn;
9090
private String structName;
9191
private String[] structColumnNames;
92+
private transient Boolean simpleRecord;
9293
// lazily computed based on 'properties' field: invalidate by setting to null when properties are modified
9394
private transient List<Selectable> cachedSelectables;
9495
// lazily computed based on 'properties' field: invalidate by setting to null when properties are modified
@@ -315,6 +316,7 @@ public String getParentProperty() {
315316

316317
public void setComponentClassName(String componentClass) {
317318
this.componentClassName = componentClass;
319+
this.simpleRecord = null;
318320
}
319321

320322
public void setEmbedded(boolean embedded) {
@@ -777,26 +779,33 @@ private int[] sortProperties(boolean forceRetainOriginalOrder) {
777779
return this.originalPropertyOrder = originalPropertyOrder;
778780
}
779781

780-
private boolean isSimpleRecord() {
781-
// A simple record is given, when the properties match the order of the record component names
782-
final Class<?> componentClass = resolveComponentClass();
783-
if ( customInstantiator != null ) {
784-
return false;
785-
}
786-
if ( componentClass == null || !ReflectHelper.isRecord( componentClass ) ) {
787-
return false;
788-
}
789-
final String[] recordComponentNames = ReflectHelper.getRecordComponentNames( componentClass );
790-
if ( recordComponentNames.length != properties.size() ) {
791-
return false;
792-
}
793-
for ( int i = 0; i < recordComponentNames.length; i++ ) {
794-
if ( !recordComponentNames[i].equals( properties.get( i ).getName() ) ) {
795-
return false;
782+
public void setSimpleRecord(boolean simpleRecord) {
783+
this.simpleRecord = simpleRecord;
784+
}
785+
786+
public boolean isSimpleRecord() {
787+
Boolean simple = simpleRecord;
788+
if ( simple == null ) {
789+
// A simple record is given, when the properties match the order of the record component names
790+
final Class<?> componentClass = resolveComponentClass();
791+
if ( customInstantiator != null ) {
792+
return simpleRecord = false;
793+
}
794+
if ( componentClass == null || !ReflectHelper.isRecord( componentClass ) ) {
795+
return simpleRecord = false;
796796
}
797+
final String[] recordComponentNames = ReflectHelper.getRecordComponentNames( componentClass );
798+
if ( recordComponentNames.length != properties.size() ) {
799+
return simpleRecord = false;
800+
}
801+
for ( int i = 0; i < recordComponentNames.length; i++ ) {
802+
if ( !recordComponentNames[i].equals( properties.get( i ).getName() ) ) {
803+
return simpleRecord = false;
804+
}
805+
}
806+
simple = simpleRecord = true;
797807
}
798-
799-
return true;
808+
return simple;
800809
}
801810

802811
public Class<? extends EmbeddableInstantiator> getCustomInstantiator() {

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/IdClassEmbeddable.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ public IdClassEmbeddable(
7474
.getJavaTypeRegistry()
7575
.resolveManagedTypeDescriptor( idClassSource.getComponentClass() );
7676

77-
this.representationStrategy = new IdClassRepresentationStrategy( this );
77+
this.representationStrategy = new IdClassRepresentationStrategy(
78+
this,
79+
idClassSource.sortProperties() == null,
80+
idClassSource::getPropertyNames
81+
);
7882

7983
final PropertyAccess propertyAccess = PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess(
8084
null,
@@ -101,7 +105,7 @@ public IdClassEmbeddable(
101105
propertyAccess
102106
);
103107

104-
final CompositeType idClassType = (CompositeType) idClassSource.getType();
108+
final CompositeType idClassType = idClassSource.getType();
105109
( (CompositeTypeImplementor) idClassType ).injectMappingModelPart( embedded, creationProcess );
106110

107111
creationProcess.registerInitializationCallback(
@@ -127,10 +131,16 @@ public IdClassEmbeddable(
127131
super( new MutableAttributeMappingList( inverseMappingType.attributeMappings.size() ) );
128132

129133
this.navigableRole = inverseMappingType.getNavigableRole();
130-
this.idMapping = (NonAggregatedIdentifierMapping) valueMapping;;
134+
this.idMapping = (NonAggregatedIdentifierMapping) valueMapping;
131135
this.virtualIdEmbeddable = (VirtualIdEmbeddable) valueMapping.getEmbeddableTypeDescriptor();
132136
this.javaType = inverseMappingType.javaType;
133-
this.representationStrategy = new IdClassRepresentationStrategy( this );
137+
this.representationStrategy = new IdClassRepresentationStrategy( this, false, () -> {
138+
final String[] attributeNames = new String[inverseMappingType.getNumberOfAttributeMappings()];
139+
for ( int i = 0; i < attributeNames.length; i++ ) {
140+
attributeNames[i] = inverseMappingType.getAttributeMapping( i ).getAttributeName();
141+
}
142+
return attributeNames;
143+
} );
134144
this.embedded = valueMapping;
135145
this.selectableMappings = selectableMappings;
136146
creationProcess.registerInitializationCallback(

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/IdClassRepresentationStrategy.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
package org.hibernate.metamodel.mapping.internal;
88

99
import java.util.Locale;
10+
import java.util.function.Supplier;
1011

1112
import org.hibernate.HibernateException;
1213
import org.hibernate.bytecode.spi.ReflectionOptimizer;
1314
import org.hibernate.mapping.Property;
1415
import org.hibernate.metamodel.RepresentationMode;
1516
import org.hibernate.metamodel.internal.EmbeddableInstantiatorPojoStandard;
17+
import org.hibernate.metamodel.internal.EmbeddableInstantiatorRecordIndirecting;
1618
import org.hibernate.metamodel.internal.EmbeddableInstantiatorRecordStandard;
1719
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
1820
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
@@ -29,11 +31,29 @@ public class IdClassRepresentationStrategy implements EmbeddableRepresentationSt
2931
private final JavaType<?> idClassType;
3032
private final EmbeddableInstantiator instantiator;
3133

32-
public IdClassRepresentationStrategy(IdClassEmbeddable idClassEmbeddable) {
34+
public IdClassRepresentationStrategy(
35+
IdClassEmbeddable idClassEmbeddable,
36+
boolean simplePropertyOrder,
37+
Supplier<String[]> attributeNamesAccess) {
3338
this.idClassType = idClassEmbeddable.getMappedJavaType();
34-
this.instantiator = isRecord( idClassType.getJavaTypeClass() ) ?
35-
new EmbeddableInstantiatorRecordStandard( idClassType.getJavaTypeClass() ) :
36-
new EmbeddableInstantiatorPojoStandard( idClassType, () -> idClassEmbeddable );
39+
final Class<?> javaTypeClass = idClassType.getJavaTypeClass();
40+
if ( isRecord( javaTypeClass ) ) {
41+
if ( simplePropertyOrder ) {
42+
this.instantiator = new EmbeddableInstantiatorRecordStandard( javaTypeClass );
43+
}
44+
else {
45+
this.instantiator = EmbeddableInstantiatorRecordIndirecting.of(
46+
javaTypeClass,
47+
attributeNamesAccess.get()
48+
);
49+
}
50+
}
51+
else {
52+
this.instantiator = new EmbeddableInstantiatorPojoStandard(
53+
idClassType,
54+
() -> idClassEmbeddable
55+
);
56+
}
3757
}
3858

3959
@Override

0 commit comments

Comments
 (0)