@@ -80,7 +80,7 @@ public class MappingJdbcConverter extends MappingRelationalConverter implements
8080 * {@link #MappingJdbcConverter(RelationalMappingContext, RelationResolver, CustomConversions, JdbcTypeFactory)}
8181 * (MappingContext, RelationResolver, JdbcTypeFactory)} to convert arrays and large objects into JDBC-specific types.
8282 *
83- * @param context must not be {@literal null}.
83+ * @param context must not be {@literal null}.
8484 * @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}.
8585 */
8686 public MappingJdbcConverter (RelationalMappingContext context , RelationResolver relationResolver ) {
@@ -98,12 +98,12 @@ public MappingJdbcConverter(RelationalMappingContext context, RelationResolver r
9898 /**
9999 * Creates a new {@link MappingJdbcConverter} given {@link MappingContext}.
100100 *
101- * @param context must not be {@literal null}.
101+ * @param context must not be {@literal null}.
102102 * @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}.
103- * @param typeFactory must not be {@literal null}
103+ * @param typeFactory must not be {@literal null}
104104 */
105105 public MappingJdbcConverter (RelationalMappingContext context , RelationResolver relationResolver ,
106- CustomConversions conversions , JdbcTypeFactory typeFactory ) {
106+ CustomConversions conversions , JdbcTypeFactory typeFactory ) {
107107
108108 super (context , conversions );
109109
@@ -220,7 +220,7 @@ private boolean canWriteAsJdbcValue(@Nullable Object value) {
220220 return true ;
221221 }
222222
223- if (value instanceof AggregateReference aggregateReference ) {
223+ if (value instanceof AggregateReference <?, ?> aggregateReference ) {
224224 return canWriteAsJdbcValue (aggregateReference .getId ());
225225 }
226226
@@ -285,7 +285,7 @@ public <R> R readAndResolve(TypeInformation<R> type, RowDocument source, Identif
285285
286286 @ Override
287287 protected RelationalPropertyValueProvider newValueProvider (RowDocumentAccessor documentAccessor ,
288- ValueExpressionEvaluator evaluator , ConversionContext context ) {
288+ ValueExpressionEvaluator evaluator , ConversionContext context ) {
289289
290290 if (context instanceof ResolvingConversionContext rcc ) {
291291
@@ -314,7 +314,7 @@ class ResolvingRelationalPropertyValueProvider implements RelationalPropertyValu
314314 private final Identifier identifier ;
315315
316316 private ResolvingRelationalPropertyValueProvider (AggregatePathValueProvider delegate , RowDocumentAccessor accessor ,
317- ResolvingConversionContext context , Identifier identifier ) {
317+ ResolvingConversionContext context , Identifier identifier ) {
318318
319319 AggregatePath path = context .aggregatePath ();
320320
@@ -323,15 +323,15 @@ private ResolvingRelationalPropertyValueProvider(AggregatePathValueProvider dele
323323 this .context = context ;
324324 this .identifier = path .isEntity ()
325325 ? potentiallyAppendIdentifier (identifier , path .getRequiredLeafEntity (),
326- property -> delegate .getValue (path .append (property )))
326+ property -> delegate .getValue (path .append (property )))
327327 : identifier ;
328328 }
329329
330330 /**
331331 * Conditionally append the identifier if the entity has an identifier property.
332332 */
333333 static Identifier potentiallyAppendIdentifier (Identifier base , RelationalPersistentEntity <?> entity ,
334- Function <RelationalPersistentProperty , Object > getter ) {
334+ Function <RelationalPersistentProperty , Object > getter ) {
335335
336336 if (entity .hasIdProperty ()) {
337337
@@ -361,24 +361,9 @@ public <T> T getPropertyValue(RelationalPersistentProperty property) {
361361
362362 if (property .isCollectionLike () || property .isMap ()) {
363363
364- Identifier identifierToUse = this .identifier ;
365- AggregatePath idDefiningParentPath = aggregatePath .getIdDefiningParentPath ();
364+ Identifier identifier = constructIdentifier (aggregatePath );
366365
367- // note that the idDefiningParentPath might not itself have an id property, but have a combination of back
368- // references and possibly keys, that form an id
369- if (idDefiningParentPath .hasIdProperty ()) {
370-
371- RelationalPersistentProperty identifier = idDefiningParentPath .getRequiredIdProperty ();
372- AggregatePath idPath = idDefiningParentPath .append (identifier );
373- Object value = delegate .getValue (idPath );
374-
375- Assert .state (value != null , "Identifier value must not be null at this point" );
376-
377- identifierToUse = Identifier .of (aggregatePath .getTableInfo ().reverseColumnInfo ().name (), value ,
378- identifier .getActualType ());
379- }
380-
381- Iterable <Object > allByPath = relationResolver .findAllByPath (identifierToUse ,
366+ Iterable <Object > allByPath = relationResolver .findAllByPath (identifier ,
382367 aggregatePath .getRequiredPersistentPropertyPath ());
383368
384369 if (property .isCollectionLike ()) {
@@ -403,6 +388,29 @@ public <T> T getPropertyValue(RelationalPersistentProperty property) {
403388 return (T ) delegate .getValue (aggregatePath );
404389 }
405390
391+ private Identifier constructIdentifier (AggregatePath aggregatePath ) {
392+
393+ Identifier identifierToUse = this .identifier ;
394+ AggregatePath idDefiningParentPath = aggregatePath .getIdDefiningParentPath ();
395+
396+ // note that the idDefiningParentPath might not itself have an id property, but have a combination of back
397+ // references and possibly keys, that form an id
398+ if (idDefiningParentPath .hasIdProperty ()) {
399+
400+ RelationalPersistentProperty idProperty = idDefiningParentPath .getRequiredIdProperty ();
401+ AggregatePath idPath = idProperty .isEntity () ? idDefiningParentPath .append (idProperty ) : idDefiningParentPath ;
402+ Identifier [] buildingIdentifier = new Identifier [] { Identifier .empty () };
403+ aggregatePath .getTableInfo ().reverseColumnInfos ().forEach ((ap , ci ) -> {
404+
405+ Object value = delegate .getValue (idPath .append (ap ));
406+ buildingIdentifier [0 ] = buildingIdentifier [0 ].withPart (ci .name (), value ,
407+ ap .getRequiredLeafProperty ().getActualType ());
408+ });
409+ identifierToUse = buildingIdentifier [0 ];
410+ }
411+ return identifierToUse ;
412+ }
413+
406414 @ Override
407415 public boolean hasValue (RelationalPersistentProperty property ) {
408416
@@ -423,7 +431,7 @@ public boolean hasValue(RelationalPersistentProperty property) {
423431 return delegate .hasValue (toUse );
424432 }
425433
426- return delegate .hasValue (aggregatePath .getTableInfo ().reverseColumnInfo ().alias ());
434+ return delegate .hasValue (aggregatePath .getTableInfo ().reverseColumnInfos (). any ().alias ());
427435 }
428436
429437 return delegate .hasValue (aggregatePath );
@@ -449,7 +457,7 @@ public boolean hasNonEmptyValue(RelationalPersistentProperty property) {
449457 return delegate .hasValue (toUse );
450458 }
451459
452- return delegate .hasValue (aggregatePath .getTableInfo ().reverseColumnInfo ().alias ());
460+ return delegate .hasValue (aggregatePath .getTableInfo ().reverseColumnInfos (). any ().alias ());
453461 }
454462
455463 return delegate .hasNonEmptyValue (aggregatePath );
@@ -460,7 +468,7 @@ public RelationalPropertyValueProvider withContext(ConversionContext context) {
460468
461469 return context == this .context ? this
462470 : new ResolvingRelationalPropertyValueProvider (delegate .withContext (context ), accessor ,
463- (ResolvingConversionContext ) context , identifier );
471+ (ResolvingConversionContext ) context , identifier );
464472 }
465473 }
466474
@@ -472,7 +480,7 @@ public RelationalPropertyValueProvider withContext(ConversionContext context) {
472480 * @param identifier
473481 */
474482 private record ResolvingConversionContext (ConversionContext delegate , AggregatePath aggregatePath ,
475- Identifier identifier ) implements ConversionContext {
483+ Identifier identifier ) implements ConversionContext {
476484
477485 @ Override
478486 public <S > S convert (Object source , TypeInformation <? extends S > typeHint ) {
0 commit comments