Browse Source

DATACMNS-1524 - Fix performance regression in QueryExecutionResultHandler.

A side effect of the fix for DATACMNS-1482 trigged source objects that already perfectly match the desired return type would still be subject to detailed inspection of potential conversions, which – by definition – will not kick in.

The code has now been changed to only trigger detailed inspection for collection values.

Related tickets: DATACMNS-1482.
pull/400/head
Oliver Drotbohm 7 years ago
parent
commit
d29fefca5b
No known key found for this signature in database
GPG Key ID: 6E42B5787543F690
  1. 56
      src/main/java/org/springframework/data/repository/core/support/QueryExecutionResultHandler.java

56
src/main/java/org/springframework/data/repository/core/support/QueryExecutionResultHandler.java

@ -16,11 +16,13 @@ @@ -16,11 +16,13 @@
package org.springframework.data.repository.core.support;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import org.springframework.core.CollectionFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService;
@ -64,6 +66,10 @@ class QueryExecutionResultHandler { @@ -64,6 +66,10 @@ class QueryExecutionResultHandler {
@Nullable
public Object postProcessInvocationResult(@Nullable Object result, Method method) {
if (!processingRequired(result, method.getReturnType())) {
return result;
}
MethodParameter parameter = new MethodParameter(method, -1);
return postProcessInvocationResult(result, 0, parameter);
@ -96,19 +102,17 @@ class QueryExecutionResultHandler { @@ -96,19 +102,17 @@ class QueryExecutionResultHandler {
// For a wrapper type, try nested resolution first
result = postProcessInvocationResult(result, nestingLevel + 1, parameter);
TypeDescriptor targetType = TypeDescriptor.valueOf(expectedReturnType);
if (conversionService.canConvert(WRAPPER_TYPE, returnTypeDescriptor)
&& !conversionService.canBypassConvert(WRAPPER_TYPE, targetType)) {
return conversionService.convert(new NullableWrapper(result), expectedReturnType);
if (conversionRequired(WRAPPER_TYPE, returnTypeDescriptor)) {
return conversionService.convert(new NullableWrapper(result), returnTypeDescriptor);
}
if (result != null
&& conversionService.canConvert(TypeDescriptor.valueOf(result.getClass()), returnTypeDescriptor)
&& !conversionService.canBypassConvert(TypeDescriptor.valueOf(result.getClass()), targetType)) {
if (result != null) {
return conversionService.convert(result, expectedReturnType);
TypeDescriptor source = TypeDescriptor.valueOf(result.getClass());
if (conversionRequired(source, returnTypeDescriptor)) {
return conversionService.convert(result, returnTypeDescriptor);
}
}
}
@ -128,6 +132,20 @@ class QueryExecutionResultHandler { @@ -128,6 +132,20 @@ class QueryExecutionResultHandler {
: null;
}
/**
* Returns whether the configured {@link ConversionService} can convert between the given {@link TypeDescriptor}s and
* the conversion will not be a no-op.
*
* @param source
* @param target
* @return
*/
private boolean conversionRequired(TypeDescriptor source, TypeDescriptor target) {
return conversionService.canConvert(source, target) //
&& !conversionService.canBypassConvert(source, target);
}
/**
* Unwraps the given value if it's a JDK 8 {@link Optional}.
*
@ -142,6 +160,22 @@ class QueryExecutionResultHandler { @@ -142,6 +160,22 @@ class QueryExecutionResultHandler {
return null;
}
return Optional.class.isInstance(source) ? Optional.class.cast(source).orElse(null) : source;
return Optional.class.isInstance(source) //
? Optional.class.cast(source).orElse(null) //
: source;
}
/**
* Returns whether we have to process the given source object in the first place.
*
* @param source can be {@literal null}.
* @param targetType must not be {@literal null}.
* @return
*/
private static boolean processingRequired(@Nullable Object source, Class<?> targetType) {
return !targetType.isInstance(source) //
|| source == null //
|| Collection.class.isInstance(source);
}
}

Loading…
Cancel
Save