2929import java .util .List ;
3030import java .util .Map ;
3131import java .util .Set ;
32+ import java .util .function .UnaryOperator ;
3233import java .util .stream .Collectors ;
3334
3435import org .springframework .core .convert .converter .Converter ;
@@ -151,7 +152,8 @@ private Object doExecute(JpaQueryExecution execution, Object[] values) {
151152 Object result = execution .execute (this , accessor );
152153
153154 ResultProcessor withDynamicProjection = method .getResultProcessor ().withDynamicProjection (accessor );
154- return withDynamicProjection .processResult (result , new TupleConverter (withDynamicProjection .getReturnedType (), method .isNativeQuery ()));
155+ return withDynamicProjection .processResult (result ,
156+ new TupleConverter (withDynamicProjection .getReturnedType (), method .isNativeQuery ()));
155157 }
156158
157159 private JpaParametersParameterAccessor obtainParameterAccessor (Object [] values ) {
@@ -306,30 +308,30 @@ static class TupleConverter implements Converter<Object, Object> {
306308
307309 private final ReturnedType type ;
308310
309- private final boolean nativeQuery ;
311+ private final UnaryOperator < Tuple > tupleWrapper ;
310312
311313 /**
312314 * Creates a new {@link TupleConverter} for the given {@link ReturnedType}.
313315 *
314316 * @param type must not be {@literal null}.
315317 */
316318 public TupleConverter (ReturnedType type ) {
317-
318319 this (type , false );
319320 }
320321
321322 /**
322323 * Creates a new {@link TupleConverter} for the given {@link ReturnedType}.
323324 *
324325 * @param type must not be {@literal null}.
325- * @param nativeQuery is this converter for native query?
326+ * @param nativeQuery whether the actual query is a native one to attempt camelCase property names to snake_case
327+ * column names translation in case the exact column name is not found using the requested property name.
326328 */
327329 public TupleConverter (ReturnedType type , boolean nativeQuery ) {
328330
329331 Assert .notNull (type , "Returned type must not be null" );
330332
331333 this .type = type ;
332- this .nativeQuery = nativeQuery ;
334+ this .tupleWrapper = nativeQuery ? FallbackTupleWrapper :: new : UnaryOperator . identity () ;
333335 }
334336
335337 @ Override
@@ -350,7 +352,7 @@ public Object convert(Object source) {
350352 }
351353 }
352354
353- return new TupleBackedMap (nativeQuery ? new NativeTupleWrapper (tuple ) : tuple );
355+ return new TupleBackedMap (tupleWrapper . apply (tuple ));
354356 }
355357
356358 /**
@@ -468,39 +470,29 @@ public Set<Entry<String, Object>> entrySet() {
468470 }
469471 }
470472
471- private static class NativeTupleWrapper implements Tuple {
472-
473- private final Tuple underlying ;
473+ private static class FallbackTupleWrapper implements Tuple {
474474
475- NativeTupleWrapper (Tuple underlying ) {
476- this .underlying = underlying ;
477- }
475+ private final Tuple delegate ;
476+ private final UnaryOperator <String > fallbackNameTransformer = JdbcUtils ::convertPropertyNameToUnderscoreName ;
478477
479- String fallback ( String alias ) {
480- return JdbcUtils . convertPropertyNameToUnderscoreName ( alias ) ;
478+ FallbackTupleWrapper ( Tuple delegate ) {
479+ this . delegate = delegate ;
481480 }
482481
483482 @ Override
484483 public <X > X get (TupleElement <X > tupleElement ) {
485- try {
486- return underlying .get (tupleElement );
487- } catch (IllegalArgumentException original ) {
488- try {
489- return underlying .get (fallback (tupleElement .getAlias ()), tupleElement .getJavaType ());
490- } catch (IllegalArgumentException ignored ) {
491- throw original ;
492- }
493- }
484+ return get (tupleElement .getAlias (), tupleElement .getJavaType ());
494485 }
495486
496487 @ Override
497- public <X > X get (String s , Class <X > aClass ) {
488+ public <X > X get (String s , Class <X > type ) {
498489 try {
499- return underlying .get (s , aClass );
490+ return delegate .get (s , type );
500491 } catch (IllegalArgumentException original ) {
501492 try {
502- return underlying .get (fallback (s ), aClass );
503- } catch (IllegalArgumentException ignored ) {
493+ return delegate .get (fallbackNameTransformer .apply (s ), type );
494+ } catch (IllegalArgumentException next ) {
495+ original .addSuppressed (next );
504496 throw original ;
505497 }
506498 }
@@ -509,34 +501,35 @@ public <X> X get(String s, Class<X> aClass) {
509501 @ Override
510502 public Object get (String s ) {
511503 try {
512- return underlying .get (s );
504+ return delegate .get (s );
513505 } catch (IllegalArgumentException original ) {
514506 try {
515- return underlying .get (fallback (s ));
516- } catch (IllegalArgumentException ignored ) {
507+ return delegate .get (fallbackNameTransformer .apply (s ));
508+ } catch (IllegalArgumentException next ) {
509+ original .addSuppressed (next );
517510 throw original ;
518511 }
519512 }
520513 }
521514
522515 @ Override
523516 public <X > X get (int i , Class <X > aClass ) {
524- return underlying .get (i , aClass );
517+ return delegate .get (i , aClass );
525518 }
526519
527520 @ Override
528521 public Object get (int i ) {
529- return underlying .get (i );
522+ return delegate .get (i );
530523 }
531524
532525 @ Override
533526 public Object [] toArray () {
534- return underlying .toArray ();
527+ return delegate .toArray ();
535528 }
536529
537530 @ Override
538531 public List <TupleElement <?>> getElements () {
539- return underlying .getElements ();
532+ return delegate .getElements ();
540533 }
541534 }
542535}
0 commit comments