Revise QuerydslPredicateBuilder nullability behavior.

We now no longer return a null Predicate from QuerydslPredicateBuilder.getPredicate(…) if the input values are empty or if the constraints are empty. Instead, we return an empty BooleanBuilder instance to avoid null handling on the calling side.

HandlerMethodArgumentsResolvers for QuerydslBindings retain their null/Optional.empty semantics.

Closes #2396
This commit is contained in:
Mark Paluch
2021-06-29 10:12:34 +02:00
parent 847738324f
commit 394187a03b
5 changed files with 51 additions and 28 deletions

View File

@@ -21,7 +21,6 @@ import java.util.Map.Entry;
import java.util.Optional;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.querydsl.binding.QuerydslBindingsFactory;
@@ -33,7 +32,6 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Predicate;
/**
@@ -84,13 +82,7 @@ public class QuerydslPredicateArgumentResolver extends QuerydslPredicateArgument
MultiValueMap<String, String> queryParameters = getQueryParameters(webRequest);
Predicate result = getPredicate(parameter, queryParameters);
if (!parameter.isOptional() && result == null) {
return new BooleanBuilder();
}
return OPTIONAL_OF_PREDICATE.isAssignableFrom(ResolvableType.forMethodParameter(parameter)) //
? Optional.ofNullable(result) //
: result;
return potentiallyConvertMethodParameterValue(parameter, result);
}
private static MultiValueMap<String, String> getQueryParameters(NativeWebRequest webRequest) {

View File

@@ -94,7 +94,6 @@ public abstract class QuerydslPredicateArgumentResolverSupport {
return false;
}
@Nullable
Predicate getPredicate(MethodParameter parameter, MultiValueMap<String, String> queryParameters) {
MergedAnnotations annotations = MergedAnnotations.from(parameter.getParameter());
@@ -112,6 +111,20 @@ public abstract class QuerydslPredicateArgumentResolverSupport {
return predicateBuilder.getPredicate(domainType, queryParameters, bindings);
}
@Nullable
static Object potentiallyConvertMethodParameterValue(MethodParameter parameter, Predicate predicate) {
if (!parameter.isOptional()) {
return predicate;
}
if (OPTIONAL_OF_PREDICATE.isAssignableFrom(ResolvableType.forMethodParameter(parameter))) {
return QuerydslPredicateBuilder.isEmpty(predicate) ? Optional.empty() : Optional.of(predicate);
}
return QuerydslPredicateBuilder.isEmpty(predicate) ? null : predicate;
}
/**
* Obtains the domain type information from the given method parameter. Will favor an explicitly registered on through
* {@link QuerydslPredicate#root()} but use the actual type of the method's return type as fallback.

View File

@@ -17,12 +17,11 @@ package org.springframework.data.web.querydsl;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.querydsl.binding.QuerydslBindingsFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.BindingContext;
@@ -30,7 +29,6 @@ import org.springframework.web.reactive.result.method.HandlerMethodArgumentResol
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
import org.springframework.web.server.ServerWebExchange;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Predicate;
/**
@@ -54,21 +52,17 @@ public class ReactiveQuerydslPredicateArgumentResolver extends QuerydslPredicate
* @see org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver(org.springframework.core.MethodParameter, org.springframework.web.reactive.BindingContext, org.springframework.web.server.ServerWebExchange)
*/
@Override
@Nullable
public Object resolveArgumentValue(MethodParameter parameter, BindingContext bindingContext,
ServerWebExchange exchange) {
MultiValueMap<String, String> queryParameters = getQueryParameters(exchange);
Predicate result = getPredicate(parameter, queryParameters);
if (!parameter.isOptional() && result == null) {
return new BooleanBuilder();
}
return OPTIONAL_OF_PREDICATE.isAssignableFrom(ResolvableType.forMethodParameter(parameter)) //
? Optional.ofNullable(result) //
: result;
return potentiallyConvertMethodParameterValue(parameter, result);
}
private static MultiValueMap<String, String> getQueryParameters(ServerWebExchange exchange) {
MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();