Skip to content

Commit 677c8b6

Browse files
mbelladesebersole
authored andcommitted
HHH-18062 Fix id-class record instantiation and mapper component
1 parent 996783c commit 677c8b6

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
@@ -495,7 +495,7 @@ private boolean mapAsIdClass(
495495
else {
496496
final boolean ignoreIdAnnotations = isIgnoreIdAnnotations();
497497
setIgnoreIdAnnotations( true );
498-
bindIdClass(
498+
final Component idClassComponent = bindIdClass(
499499
inferredData,
500500
baseInferredData,
501501
propertyHolder,
@@ -514,6 +514,9 @@ private boolean mapAsIdClass(
514514
propertyAccessor,
515515
true
516516
);
517+
if ( idClassComponent.isSimpleRecord() ) {
518+
mapper.setSimpleRecord( true );
519+
}
517520
setIgnoreIdAnnotations( ignoreIdAnnotations );
518521
for ( Property property : mapper.getProperties() ) {
519522
idPropertiesIfIdClass.add( property.getName() );
@@ -656,7 +659,7 @@ private static boolean isIdClassPkOfTheAssociatedEntity(
656659
}
657660
}
658661

659-
private void bindIdClass(
662+
private Component bindIdClass(
660663
PropertyData inferredData,
661664
PropertyData baseInferredData,
662665
PropertyHolder propertyHolder,
@@ -707,6 +710,8 @@ private void bindIdClass(
707710
rootClass.setEmbeddedIdentifier( inferredData.getPropertyClass() == null );
708711

709712
propertyHolder.setInIdClass( null );
713+
714+
return id;
710715
}
711716

712717
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
@@ -108,6 +108,7 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
108108
private QualifiedName structName;
109109
private String[] structColumnNames;
110110
private transient Class<?> componentClass;
111+
private transient Boolean simpleRecord;
111112

112113
private transient Generator builtIdentifierGenerator;
113114

@@ -377,6 +378,7 @@ public String getParentProperty() {
377378
public void setComponentClassName(String componentClass) {
378379
this.componentClassName = componentClass;
379380
this.componentClass = null;
381+
this.simpleRecord = null;
380382
}
381383

382384
public void setEmbedded(boolean embedded) {
@@ -899,26 +901,33 @@ private int[] sortProperties(boolean forceRetainOriginalOrder) {
899901
return this.originalPropertyOrder = originalPropertyOrder;
900902
}
901903

902-
private boolean isSimpleRecord() {
903-
// A simple record is given, when the properties match the order of the record component names
904-
final Class<?> componentClass = resolveComponentClass();
905-
if ( customInstantiator != null ) {
906-
return false;
907-
}
908-
if ( componentClass == null || !ReflectHelper.isRecord( componentClass ) ) {
909-
return false;
910-
}
911-
final String[] recordComponentNames = ReflectHelper.getRecordComponentNames( componentClass );
912-
if ( recordComponentNames.length != properties.size() ) {
913-
return false;
914-
}
915-
for ( int i = 0; i < recordComponentNames.length; i++ ) {
916-
if ( !recordComponentNames[i].equals( properties.get( i ).getName() ) ) {
917-
return false;
904+
public void setSimpleRecord(boolean simpleRecord) {
905+
this.simpleRecord = simpleRecord;
906+
}
907+
908+
public boolean isSimpleRecord() {
909+
Boolean simple = simpleRecord;
910+
if ( simple == null ) {
911+
// A simple record is given, when the properties match the order of the record component names
912+
final Class<?> componentClass = resolveComponentClass();
913+
if ( customInstantiator != null ) {
914+
return simpleRecord = false;
915+
}
916+
if ( componentClass == null || !ReflectHelper.isRecord( componentClass ) ) {
917+
return simpleRecord = false;
918918
}
919+
final String[] recordComponentNames = ReflectHelper.getRecordComponentNames( componentClass );
920+
if ( recordComponentNames.length != properties.size() ) {
921+
return simpleRecord = false;
922+
}
923+
for ( int i = 0; i < recordComponentNames.length; i++ ) {
924+
if ( !recordComponentNames[i].equals( properties.get( i ).getName() ) ) {
925+
return simpleRecord = false;
926+
}
927+
}
928+
simple = simpleRecord = true;
919929
}
920-
921-
return true;
930+
return simple;
922931
}
923932

924933
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.getJavaTypeClass(), () -> 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.getJavaTypeClass(),
54+
() -> idClassEmbeddable
55+
);
56+
}
3757
}
3858

3959
@Override

0 commit comments

Comments
 (0)