26
26
27
27
import org .apache .commons .logging .Log ;
28
28
import org .apache .commons .logging .LogFactory ;
29
-
30
29
import org .springframework .context .ApplicationContextAware ;
31
30
import org .springframework .core .convert .ConverterNotFoundException ;
32
31
import org .springframework .core .convert .converter .Converter ;
@@ -81,7 +80,7 @@ public class MappingJdbcConverter extends MappingRelationalConverter implements
81
80
* {@link #MappingJdbcConverter(RelationalMappingContext, RelationResolver, CustomConversions, JdbcTypeFactory)}
82
81
* (MappingContext, RelationResolver, JdbcTypeFactory)} to convert arrays and large objects into JDBC-specific types.
83
82
*
84
- * @param context must not be {@literal null}.
83
+ * @param context must not be {@literal null}.
85
84
* @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}.
86
85
*/
87
86
public MappingJdbcConverter (RelationalMappingContext context , RelationResolver relationResolver ) {
@@ -99,12 +98,12 @@ public MappingJdbcConverter(RelationalMappingContext context, RelationResolver r
99
98
/**
100
99
* Creates a new {@link MappingJdbcConverter} given {@link MappingContext}.
101
100
*
102
- * @param context must not be {@literal null}.
101
+ * @param context must not be {@literal null}.
103
102
* @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}.
104
- * @param typeFactory must not be {@literal null}
103
+ * @param typeFactory must not be {@literal null}
105
104
*/
106
105
public MappingJdbcConverter (RelationalMappingContext context , RelationResolver relationResolver ,
107
- CustomConversions conversions , JdbcTypeFactory typeFactory ) {
106
+ CustomConversions conversions , JdbcTypeFactory typeFactory ) {
108
107
109
108
super (context , conversions );
110
109
@@ -301,7 +300,7 @@ public <R> R readAndResolve(TypeInformation<R> type, RowDocument source, Identif
301
300
302
301
@ Override
303
302
protected RelationalPropertyValueProvider newValueProvider (RowDocumentAccessor documentAccessor ,
304
- ValueExpressionEvaluator evaluator , ConversionContext context ) {
303
+ ValueExpressionEvaluator evaluator , ConversionContext context ) {
305
304
306
305
if (context instanceof ResolvingConversionContext rcc ) {
307
306
@@ -330,7 +329,7 @@ class ResolvingRelationalPropertyValueProvider implements RelationalPropertyValu
330
329
private final Identifier identifier ;
331
330
332
331
private ResolvingRelationalPropertyValueProvider (AggregatePathValueProvider delegate , RowDocumentAccessor accessor ,
333
- ResolvingConversionContext context , Identifier identifier ) {
332
+ ResolvingConversionContext context , Identifier identifier ) {
334
333
335
334
AggregatePath path = context .aggregatePath ();
336
335
@@ -339,15 +338,15 @@ private ResolvingRelationalPropertyValueProvider(AggregatePathValueProvider dele
339
338
this .context = context ;
340
339
this .identifier = path .isEntity ()
341
340
? potentiallyAppendIdentifier (identifier , path .getRequiredLeafEntity (),
342
- property -> delegate .getValue (path .append (property )))
341
+ property -> delegate .getValue (path .append (property )))
343
342
: identifier ;
344
343
}
345
344
346
345
/**
347
346
* Conditionally append the identifier if the entity has an identifier property.
348
347
*/
349
348
static Identifier potentiallyAppendIdentifier (Identifier base , RelationalPersistentEntity <?> entity ,
350
- Function <RelationalPersistentProperty , Object > getter ) {
349
+ Function <RelationalPersistentProperty , Object > getter ) {
351
350
352
351
if (entity .hasIdProperty ()) {
353
352
@@ -422,7 +421,7 @@ public <T> T getPropertyValue(RelationalPersistentProperty property) {
422
421
@ Override
423
422
public boolean hasValue (RelationalPersistentProperty property ) {
424
423
425
- if ((property .isCollectionLike () && property .isEntity ())|| property .isMap ()) {
424
+ if ((property .isCollectionLike () && property .isEntity ()) || property .isMap ()) {
426
425
// attempt relation fetch
427
426
return true ;
428
427
}
@@ -445,12 +444,38 @@ public boolean hasValue(RelationalPersistentProperty property) {
445
444
return delegate .hasValue (aggregatePath );
446
445
}
447
446
447
+ @ Override
448
+ public boolean hasNonEmptyValue (RelationalPersistentProperty property ) {
449
+
450
+ if ((property .isCollectionLike () && property .isEntity ()) || property .isMap ()) {
451
+ // attempt relation fetch
452
+ return true ;
453
+ }
454
+
455
+ AggregatePath aggregatePath = context .aggregatePath ();
456
+
457
+ if (property .isEntity ()) {
458
+
459
+ RelationalPersistentEntity <?> entity = getMappingContext ().getRequiredPersistentEntity (property );
460
+ if (entity .hasIdProperty ()) {
461
+
462
+ RelationalPersistentProperty referenceId = entity .getRequiredIdProperty ();
463
+ AggregatePath toUse = aggregatePath .append (referenceId );
464
+ return delegate .hasValue (toUse );
465
+ }
466
+
467
+ return delegate .hasValue (aggregatePath .getTableInfo ().reverseColumnInfo ().alias ());
468
+ }
469
+
470
+ return delegate .hasNonEmptyValue (aggregatePath );
471
+ }
472
+
448
473
@ Override
449
474
public RelationalPropertyValueProvider withContext (ConversionContext context ) {
450
475
451
476
return context == this .context ? this
452
477
: new ResolvingRelationalPropertyValueProvider (delegate .withContext (context ), accessor ,
453
- (ResolvingConversionContext ) context , identifier );
478
+ (ResolvingConversionContext ) context , identifier );
454
479
}
455
480
}
456
481
@@ -462,7 +487,7 @@ public RelationalPropertyValueProvider withContext(ConversionContext context) {
462
487
* @param identifier
463
488
*/
464
489
private record ResolvingConversionContext (ConversionContext delegate , AggregatePath aggregatePath ,
465
- Identifier identifier ) implements ConversionContext {
490
+ Identifier identifier ) implements ConversionContext {
466
491
467
492
@ Override
468
493
public <S > S convert (Object source , TypeInformation <? extends S > typeHint ) {
0 commit comments