34
34
import org .springframework .data .r2dbc .dialect .MutableBindings ;
35
35
import org .springframework .data .r2dbc .dialect .R2dbcDialect ;
36
36
import org .springframework .data .r2dbc .mapping .SettableValue ;
37
+ import org .springframework .data .relational .core .dialect .Escaper ;
37
38
import org .springframework .data .relational .core .mapping .RelationalPersistentEntity ;
38
39
import org .springframework .data .relational .core .mapping .RelationalPersistentProperty ;
39
40
import org .springframework .data .relational .core .query .CriteriaDefinition ;
40
41
import org .springframework .data .relational .core .query .CriteriaDefinition .Comparator ;
42
+ import org .springframework .data .relational .core .query .ValueFunction ;
41
43
import org .springframework .data .relational .core .sql .*;
42
44
import org .springframework .data .util .ClassTypeInformation ;
45
+ import org .springframework .data .util .Pair ;
43
46
import org .springframework .data .util .TypeInformation ;
44
47
import org .springframework .lang .Nullable ;
45
48
import org .springframework .util .Assert ;
46
49
import org .springframework .util .ClassUtils ;
47
50
48
51
/**
49
- * Maps {@link Criteria} and {@link Sort} objects considering mapping metadata and dialect-specific conversion.
52
+ * Maps {@link CriteriaDefinition} and {@link Sort} objects considering mapping metadata and dialect-specific
53
+ * conversion.
50
54
*
51
55
* @author Mark Paluch
52
56
* @author Roman Chigvintsev
@@ -344,7 +348,13 @@ private Condition mapCondition(CriteriaDefinition criteria, MutableBindings bind
344
348
345
349
mappedValue = convertValue (settableValue .getValue (), propertyField .getTypeHint ());
346
350
typeHint = getTypeHint (mappedValue , actualType .getType (), settableValue );
351
+ } else if (criteria .getValue () instanceof ValueFunction ) {
347
352
353
+ ValueFunction <Object > valueFunction = (ValueFunction <Object >) criteria .getValue ();
354
+ Object value = valueFunction .apply (getEscaper (criteria .getComparator ()));
355
+
356
+ mappedValue = convertValue (value , propertyField .getTypeHint ());
357
+ typeHint = actualType .getType ();
348
358
} else {
349
359
350
360
mappedValue = convertValue (criteria .getValue (), propertyField .getTypeHint ());
@@ -354,6 +364,15 @@ private Condition mapCondition(CriteriaDefinition criteria, MutableBindings bind
354
364
return createCondition (column , mappedValue , typeHint , bindings , criteria .getComparator (), criteria .isIgnoreCase ());
355
365
}
356
366
367
+ private Escaper getEscaper (Comparator comparator ) {
368
+
369
+ if (comparator == Comparator .LIKE || comparator == Comparator .NOT_LIKE ) {
370
+ return dialect .getLikeEscaper ();
371
+ }
372
+
373
+ return Escaper .DEFAULT ;
374
+ }
375
+
357
376
/**
358
377
* Potentially convert the {@link SettableValue}.
359
378
*
@@ -376,6 +395,21 @@ protected Object convertValue(@Nullable Object value, TypeInformation<?> typeInf
376
395
return null ;
377
396
}
378
397
398
+ if (value instanceof Pair ) {
399
+
400
+ Pair <Object , Object > pair = (Pair <Object , Object >) value ;
401
+
402
+ Object first = convertValue (pair .getFirst (),
403
+ typeInformation .getActualType () != null ? typeInformation .getRequiredActualType ()
404
+ : ClassTypeInformation .OBJECT );
405
+
406
+ Object second = convertValue (pair .getSecond (),
407
+ typeInformation .getActualType () != null ? typeInformation .getRequiredActualType ()
408
+ : ClassTypeInformation .OBJECT );
409
+
410
+ return Pair .of (first , second );
411
+ }
412
+
379
413
if (value instanceof Iterable ) {
380
414
381
415
List <Object > mapped = new ArrayList <>();
@@ -456,6 +490,19 @@ private Condition createCondition(Column column, @Nullable Object mappedValue, C
456
490
return condition ;
457
491
}
458
492
493
+ if (comparator == Comparator .BETWEEN || comparator == Comparator .NOT_BETWEEN ) {
494
+
495
+ Pair <Object , Object > pair = (Pair <Object , Object >) mappedValue ;
496
+
497
+ Expression begin = bind (pair .getFirst (), valueType , bindings ,
498
+ bindings .nextMarker (column .getName ().getReference ()), ignoreCase );
499
+ Expression end = bind (mappedValue , valueType , bindings , bindings .nextMarker (column .getName ().getReference ()),
500
+ ignoreCase );
501
+
502
+ return comparator == Comparator .BETWEEN ? Conditions .between (columnExpression , begin , end )
503
+ : Conditions .notBetween (columnExpression , begin , end );
504
+ }
505
+
459
506
BindMarker bindMarker = bindings .nextMarker (column .getName ().getReference ());
460
507
461
508
switch (comparator ) {
@@ -505,6 +552,10 @@ Field createPropertyField(@Nullable RelationalPersistentEntity<?> entity, SqlIde
505
552
return entity == null ? new Field (key ) : new MetadataBackedField (key , entity , mappingContext );
506
553
}
507
554
555
+ Class <?> getTypeHint (@ Nullable Object mappedValue , Class <?> propertyType ) {
556
+ return propertyType ;
557
+ }
558
+
508
559
Class <?> getTypeHint (@ Nullable Object mappedValue , Class <?> propertyType , SettableValue settableValue ) {
509
560
510
561
if (mappedValue == null || propertyType .equals (Object .class )) {
0 commit comments