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.
This commit is contained in:
@@ -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 {
|
||||
@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 {
|
||||
// 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 {
|
||||
: 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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user