24
24
import java .util .List ;
25
25
26
26
import org .springframework .data .jpa .provider .PersistenceProvider ;
27
- import org .springframework .data .jpa .repository .query .JpaParameters .JpaParameter ;
28
27
import org .springframework .data .repository .query .parser .Part .Type ;
29
28
import org .springframework .lang .Nullable ;
30
29
import org .springframework .util .Assert ;
@@ -151,8 +150,8 @@ public Object prepare(@Nullable Object valueToBind) {
151
150
/**
152
151
* Check whether the {@code other} binding uses the same bind target.
153
152
*
154
- * @param other
155
- * @return
153
+ * @param other must not be {@literal null}.
154
+ * @return {@code true} if the other binding uses the same parameter to bind to as this one.
156
155
*/
157
156
public boolean bindsTo (ParameterBinding other ) {
158
157
@@ -171,6 +170,17 @@ public boolean bindsTo(ParameterBinding other) {
171
170
return false ;
172
171
}
173
172
173
+ /**
174
+ * Check whether this binding can be bound as the {@code other} binding by checking its type and origin. Subclasses
175
+ * may override this method to include other properties for the compatibility check.
176
+ *
177
+ * @param other
178
+ * @return {@code true} if the other binding is compatible with this one.
179
+ */
180
+ public boolean isCompatibleWith (ParameterBinding other ) {
181
+ return other .getClass () == getClass () && other .getOrigin ().equals (getOrigin ());
182
+ }
183
+
174
184
/**
175
185
* Represents a {@link ParameterBinding} in a JPQL query augmented with instructions of how to apply a parameter as an
176
186
* {@code IN} parameter.
@@ -294,6 +304,16 @@ public String toString() {
294
304
getType ());
295
305
}
296
306
307
+ @ Override
308
+ public boolean isCompatibleWith (ParameterBinding binding ) {
309
+
310
+ if (super .isCompatibleWith (binding ) && binding instanceof LikeParameterBinding other ) {
311
+ return getType () == other .getType ();
312
+ }
313
+
314
+ return false ;
315
+ }
316
+
297
317
/**
298
318
* Extracts the like {@link Type} from the given JPA like expression.
299
319
*
@@ -319,52 +339,12 @@ static Type getLikeTypeFrom(String expression) {
319
339
}
320
340
}
321
341
322
- static class ParameterImpl <T > implements jakarta .persistence .Parameter <T > {
323
-
324
- private final BindingIdentifier identifier ;
325
- private final Class <T > parameterType ;
326
-
327
- /**
328
- * Creates a new {@link ParameterImpl} for the given {@link JpaParameter} and {@link ParameterBinding}.
329
- *
330
- * @param parameter can be {@literal null}.
331
- * @param binding must not be {@literal null}.
332
- * @return a {@link jakarta.persistence.Parameter} object based on the information from the arguments.
333
- */
334
- static jakarta .persistence .Parameter <?> of (@ Nullable JpaParameter parameter , ParameterBinding binding ) {
335
-
336
- Class <?> type = parameter == null ? Object .class : parameter .getType ();
337
-
338
- return new ParameterImpl <>(binding .getIdentifier (), type );
339
- }
340
-
341
- public ParameterImpl (BindingIdentifier identifier , Class <T > parameterType ) {
342
- this .identifier = identifier ;
343
- this .parameterType = parameterType ;
344
- }
345
-
346
- @ Nullable
347
- @ Override
348
- public String getName () {
349
- return identifier .hasName () ? identifier .getName () : null ;
350
- }
351
-
352
- @ Nullable
353
- @ Override
354
- public Integer getPosition () {
355
- return identifier .hasPosition () ? identifier .getPosition () : null ;
356
- }
357
-
358
- @ Override
359
- public Class <T > getParameterType () {
360
- return parameterType ;
361
- }
362
-
363
- }
364
-
365
342
/**
366
343
* Identifies a binding parameter by name, position or both. Used to bind parameters to a query or to describe a
367
344
* {@link MethodInvocationArgument} origin.
345
+ *
346
+ * @author Mark Paluch
347
+ * @since 3.1.2
368
348
*/
369
349
sealed interface BindingIdentifier permits Named ,Indexed ,NamedAndIndexed {
370
350
@@ -453,6 +433,11 @@ public boolean hasName() {
453
433
public String getName () {
454
434
return name ();
455
435
}
436
+
437
+ @ Override
438
+ public String toString () {
439
+ return name ();
440
+ }
456
441
}
457
442
458
443
private record Indexed (int position ) implements BindingIdentifier {
@@ -466,6 +451,11 @@ public boolean hasPosition() {
466
451
public int getPosition () {
467
452
return position ();
468
453
}
454
+
455
+ @ Override
456
+ public String toString () {
457
+ return "[" + position () + "]" ;
458
+ }
469
459
}
470
460
471
461
private record NamedAndIndexed (String name , int position ) implements BindingIdentifier {
@@ -489,10 +479,18 @@ public boolean hasPosition() {
489
479
public int getPosition () {
490
480
return position ();
491
481
}
482
+
483
+ @ Override
484
+ public String toString () {
485
+ return "[" + name () + ", " + position () + "]" ;
486
+ }
492
487
}
493
488
494
489
/**
495
490
* Value type hierarchy to describe where a binding parameter comes from, either method call or an expression.
491
+ *
492
+ * @author Mark Paluch
493
+ * @since 3.1.2
496
494
*/
497
495
sealed interface ParameterOrigin permits Expression ,MethodInvocationArgument {
498
496
@@ -508,11 +506,11 @@ static Expression ofExpression(String expression) {
508
506
509
507
/**
510
508
* Creates a {@link MethodInvocationArgument} object for {@code name} and {@code position}. Either the name or the
511
- * position must be given,
509
+ * position must be given.
512
510
*
513
511
* @param name the parameter name from the method invocation, can be {@literal null}.
514
512
* @param position the parameter position (1-based) from the method invocation, can be {@literal null}.
515
- * @return {@link MethodInvocationArgument} object for {@code name} and {@code position}
513
+ * @return {@link MethodInvocationArgument} object for {@code name} and {@code position}.
516
514
*/
517
515
static MethodInvocationArgument ofParameter (@ Nullable String name , @ Nullable Integer position ) {
518
516
@@ -528,26 +526,43 @@ static MethodInvocationArgument ofParameter(@Nullable String name, @Nullable Int
528
526
return ofParameter (identifier );
529
527
}
530
528
529
+ /**
530
+ * Creates a {@link MethodInvocationArgument} object for {@code position}.
531
+ *
532
+ * @param position the parameter position (1-based) from the method invocation.
533
+ * @return {@link MethodInvocationArgument} object for {@code position}.
534
+ */
535
+ static MethodInvocationArgument ofParameter (int position ) {
536
+ return ofParameter (BindingIdentifier .of (position ));
537
+ }
538
+
531
539
/**
532
540
* Creates a {@link MethodInvocationArgument} using {@link BindingIdentifier}.
533
541
*
534
542
* @param identifier must not be {@literal null}.
535
543
* @return {@link MethodInvocationArgument} for {@link BindingIdentifier}.
536
544
*/
537
545
static MethodInvocationArgument ofParameter (BindingIdentifier identifier ) {
538
-
539
546
return new MethodInvocationArgument (identifier );
540
547
}
541
548
549
+ /**
550
+ * @return {@code true} if the origin is a method argument reference.
551
+ */
542
552
boolean isMethodArgument ();
543
553
554
+ /**
555
+ * @return {@code true} if the origin is an expression.
556
+ */
544
557
boolean isExpression ();
545
558
}
546
559
547
560
/**
548
561
* Value object capturing the expression of which a binding parameter originates.
549
562
*
550
563
* @param expression
564
+ * @author Mark Paluch
565
+ * @since 3.1.2
551
566
*/
552
567
public record Expression (String expression ) implements ParameterOrigin {
553
568
@@ -566,6 +581,8 @@ public boolean isExpression() {
566
581
* Value object capturing the method invocation parameter reference.
567
582
*
568
583
* @param identifier
584
+ * @author Mark Paluch
585
+ * @since 3.1.2
569
586
*/
570
587
public record MethodInvocationArgument (BindingIdentifier identifier ) implements ParameterOrigin {
571
588
0 commit comments