DATACMNS-867 - First draft.
This commit is contained in:
@@ -17,7 +17,6 @@ package org.springframework.data.querydsl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -130,15 +129,6 @@ public class QuerydslRepositoryInvokerAdapter implements RepositoryInvoker {
|
||||
return delegate.invokeFindOne(id);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.support.RepositoryInvoker#invokeQueryMethod(java.lang.reflect.Method, java.util.Map, org.springframework.data.domain.Pageable, org.springframework.data.domain.Sort)
|
||||
*/
|
||||
@Override
|
||||
public Object invokeQueryMethod(Method method, Map<String, String[]> parameters, Pageable pageable, Sort sort) {
|
||||
return delegate.invokeQueryMethod(method, parameters, pageable, sort);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.support.RepositoryInvoker#invokeQueryMethod(java.lang.reflect.Method, org.springframework.util.MultiValueMap, org.springframework.data.domain.Pageable, org.springframework.data.domain.Sort)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.querydsl.binding;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.querydsl.core.types.Path;
|
||||
import com.querydsl.core.types.Predicate;
|
||||
@@ -40,5 +41,5 @@ public interface MultiValueBinding<T extends Path<? extends S>, S> {
|
||||
* @return can be {@literal null}, in which case the binding will not be incorporated in the overall {@link Predicate}
|
||||
* .
|
||||
*/
|
||||
Predicate bind(T path, Collection<? extends S> value);
|
||||
Optional<Predicate> bind(T path, Collection<? extends S> value);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.querydsl.binding;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.querydsl.core.types.Path;
|
||||
import com.querydsl.core.types.Predicate;
|
||||
|
||||
/**
|
||||
* {@link OptionalValueBinding} creates a {@link Predicate} out of given {@link Path} and value. Used for specific
|
||||
* parameter treatment in {@link QuerydslBindings}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @since 1.11
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface OptionalValueBinding<T extends Path<? extends S>, S> {
|
||||
|
||||
/**
|
||||
* Returns the predicate to be applied to the given {@link Path} for the given value. The given value will be the
|
||||
* first the first one provided for the given path and converted into the expected type.
|
||||
*
|
||||
* @param path {@link Path} to the property. Will not be {@literal null}.
|
||||
* @param value the value that should be bound. Will not be {@literal null}.
|
||||
* @return can be {@literal null}, in which case the binding will not be incorporated in the overall {@link Predicate}
|
||||
* .
|
||||
*/
|
||||
Optional<Predicate> bind(T path, Optional<? extends S> value);
|
||||
}
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.querydsl.binding;
|
||||
|
||||
import static org.springframework.data.querydsl.QueryDslUtils.*;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Value;
|
||||
@@ -24,15 +22,16 @@ import lombok.Value;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.mapping.PropertyPath;
|
||||
import org.springframework.data.mapping.PropertyReferenceException;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.Optionals;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -42,7 +41,7 @@ import com.querydsl.core.types.Predicate;
|
||||
|
||||
/**
|
||||
* {@link QuerydslBindings} allows definition of path specific bindings.
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* new QuerydslBindings() {
|
||||
@@ -53,7 +52,7 @@ import com.querydsl.core.types.Predicate;
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* The bindings can either handle a single - see {@link PathBinder#first(SingleValueBinding)} - (the first in case
|
||||
* multiple ones are supplied) or multiple - see {@link PathBinder#all(MultiValueBinding)} - value binding. If exactly
|
||||
* one path is deployed, an {@link AliasingPathBinder} is returned which - as the name suggests - allows aliasing of
|
||||
@@ -61,7 +60,7 @@ import com.querydsl.core.types.Predicate;
|
||||
* <p>
|
||||
* {@link QuerydslBindings} are usually manipulated using a {@link QuerydslBinderCustomizer}, either implemented
|
||||
* directly or using a default method on a Spring Data repository.
|
||||
*
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @since 1.11
|
||||
@@ -90,7 +89,7 @@ public class QuerydslBindings {
|
||||
|
||||
/**
|
||||
* Returns an {@link AliasingPathBinder} for the given {@link Path} to define bindings for them.
|
||||
*
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -100,17 +99,18 @@ public class QuerydslBindings {
|
||||
|
||||
/**
|
||||
* Returns a new {@link PathBinder} for the given {@link Path}s to define bindings for them.
|
||||
*
|
||||
*
|
||||
* @param paths must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final <T extends Path<S>, S> PathBinder<T, S> bind(T... paths) {
|
||||
return new PathBinder<T, S>(paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link TypeBinder} for the given type.
|
||||
*
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -121,7 +121,7 @@ public class QuerydslBindings {
|
||||
/**
|
||||
* Exclude properties from binding. Exclusion of all properties of a nested type can be done by exclusion on a higher
|
||||
* level. E.g. {@code address} would exclude both {@code address.city} and {@code address.street}.
|
||||
*
|
||||
*
|
||||
* @param paths must not be {@literal null} or empty.
|
||||
*/
|
||||
public final void excluding(Path<?>... paths) {
|
||||
@@ -129,13 +129,13 @@ public class QuerydslBindings {
|
||||
Assert.notEmpty(paths, "At least one path has to be provided!");
|
||||
|
||||
for (Path<?> path : paths) {
|
||||
this.blackList.add(toDotPath(path));
|
||||
this.blackList.add(toDotPath(Optional.of(path)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Include properties for binding. Include the property considered a binding candidate.
|
||||
*
|
||||
*
|
||||
* @param properties must not be {@literal null} or empty.
|
||||
*/
|
||||
public final void including(Path<?>... paths) {
|
||||
@@ -143,7 +143,7 @@ public class QuerydslBindings {
|
||||
Assert.notEmpty(paths, "At least one path has to be provided!");
|
||||
|
||||
for (Path<?> path : paths) {
|
||||
this.whiteList.add(toDotPath(path));
|
||||
this.whiteList.add(toDotPath(Optional.of(path)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ public class QuerydslBindings {
|
||||
* Returns whether to exclude all properties for which no explicit binding has been defined or it has been explicitly
|
||||
* white-listed. This defaults to {@literal false} which means that for properties without an explicitly defined
|
||||
* binding a type specific default binding will be applied.
|
||||
*
|
||||
*
|
||||
* @param excludeUnlistedProperties
|
||||
* @return
|
||||
* @see #including(String...)
|
||||
@@ -165,7 +165,7 @@ public class QuerydslBindings {
|
||||
|
||||
/**
|
||||
* Returns whether the given path is available on the given type.
|
||||
*
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
@@ -180,7 +180,7 @@ public class QuerydslBindings {
|
||||
|
||||
/**
|
||||
* Returns whether the given path is available on the given type.
|
||||
*
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @param type
|
||||
* @return
|
||||
@@ -196,12 +196,12 @@ public class QuerydslBindings {
|
||||
/**
|
||||
* Returns the {@link SingleValueBinding} for the given {@link PropertyPath}. Prefers a path configured for the
|
||||
* specific path but falls back to the builder registered for a given type.
|
||||
*
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <S extends Path<? extends T>, T> MultiValueBinding<S, T> getBindingForPath(PathInformation path) {
|
||||
public <S extends Path<? extends T>, T> Optional<MultiValueBinding<S, T>> getBindingForPath(PathInformation path) {
|
||||
|
||||
Assert.notNull(path, "PropertyPath must not be null!");
|
||||
|
||||
@@ -209,30 +209,29 @@ public class QuerydslBindings {
|
||||
|
||||
if (pathAndBinding != null) {
|
||||
|
||||
MultiValueBinding<S, T> binding = pathAndBinding.getBinding();
|
||||
Optional<MultiValueBinding<S, T>> binding = pathAndBinding.getBinding();
|
||||
|
||||
if (binding != null) {
|
||||
return pathAndBinding.getBinding();
|
||||
if (binding.isPresent()) {
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
|
||||
pathAndBinding = (PathAndBinding<S, T>) typeSpecs.get(path.getLeafType());
|
||||
|
||||
return pathAndBinding == null ? null : pathAndBinding.getBinding();
|
||||
return pathAndBinding == null ? Optional.empty() : pathAndBinding.getBinding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Path} for the {@link PropertyPath} instance.
|
||||
*
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Path<?> getExistingPath(PathInformation path) {
|
||||
Optional<Path<?>> getExistingPath(PathInformation path) {
|
||||
|
||||
Assert.notNull(path, "PropertyPath must not be null!");
|
||||
|
||||
PathAndBinding<?, ?> pathAndBuilder = pathSpecs.get(path.toDotPath());
|
||||
return pathAndBuilder == null ? null : pathAndBuilder.getPath();
|
||||
return Optional.ofNullable(pathSpecs.get(path.toDotPath())).flatMap(it -> it.getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -252,7 +251,9 @@ public class QuerydslBindings {
|
||||
}
|
||||
|
||||
if (pathSpecs.containsKey(path)) {
|
||||
return QuerydslPathInformation.of(pathSpecs.get(path).getPath());
|
||||
return pathSpecs.get(path).getPath()//
|
||||
.map(it -> QuerydslPathInformation.of(it))//
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -265,7 +266,7 @@ public class QuerydslBindings {
|
||||
|
||||
/**
|
||||
* Checks if a given {@link PropertyPath} should be visible for binding values.
|
||||
*
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
@@ -292,7 +293,7 @@ public class QuerydslBindings {
|
||||
/**
|
||||
* Returns whether the given path is visible, which means either an alias and not explicitly blacklisted, explicitly
|
||||
* white listed or not on the black list if no white list configured.
|
||||
*
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -310,6 +311,17 @@ public class QuerydslBindings {
|
||||
return whiteList.contains(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property path for the given {@link Path}.
|
||||
*
|
||||
* @param path can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private static String toDotPath(Optional<Path<?>> path) {
|
||||
return path.map(it -> it.toString().substring(it.getMetadata().getRootPath().getMetadata().getName().length() + 1))
|
||||
.orElse("");
|
||||
}
|
||||
|
||||
/**
|
||||
* A binder for {@link Path}s.
|
||||
*
|
||||
@@ -321,9 +333,10 @@ public class QuerydslBindings {
|
||||
|
||||
/**
|
||||
* Creates a new {@link PathBinder} for the given {@link Path}s.
|
||||
*
|
||||
*
|
||||
* @param paths must not be {@literal null} or empty.
|
||||
*/
|
||||
@SafeVarargs
|
||||
PathBinder(P... paths) {
|
||||
|
||||
Assert.notEmpty(paths, "At least one path has to be provided!");
|
||||
@@ -332,20 +345,26 @@ public class QuerydslBindings {
|
||||
|
||||
/**
|
||||
* Defines the given {@link SingleValueBinding} to be used for the paths.
|
||||
*
|
||||
*
|
||||
* @param binding must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public void first(SingleValueBinding<P, T> binding) {
|
||||
public void firstOptional(OptionalValueBinding<P, T> binding) {
|
||||
|
||||
Assert.notNull(binding, "Binding must not be null!");
|
||||
|
||||
all(new MultiValueBindingAdapter<P, T>(binding));
|
||||
all((path, value) -> binding.bind(path, Optionals.next(value.iterator())));
|
||||
}
|
||||
|
||||
public void first(SingleValueBinding<P, T> binding) {
|
||||
|
||||
Assert.notNull(binding, "Binding must not be null!");
|
||||
all((path, value) -> Optionals.next(value.iterator()).flatMap(t -> binding.bind(path, t)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the given {@link MultiValueBinding} to be used for the paths.
|
||||
*
|
||||
*
|
||||
* @param binding must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -353,9 +372,7 @@ public class QuerydslBindings {
|
||||
|
||||
Assert.notNull(binding, "Binding must not be null!");
|
||||
|
||||
for (P path : paths) {
|
||||
registerBinding(new PathAndBinding<P, T>(path, binding));
|
||||
}
|
||||
paths.forEach(path -> registerBinding(PathAndBinding.withPath(path).with(binding)));
|
||||
}
|
||||
|
||||
protected void registerBinding(PathAndBinding<P, T> binding) {
|
||||
@@ -376,7 +393,7 @@ public class QuerydslBindings {
|
||||
|
||||
/**
|
||||
* Creates a new {@link AliasingPathBinder} for the given {@link Path}.
|
||||
*
|
||||
*
|
||||
* @param paths must not be {@literal null}.
|
||||
*/
|
||||
AliasingPathBinder(P path) {
|
||||
@@ -385,11 +402,10 @@ public class QuerydslBindings {
|
||||
|
||||
/**
|
||||
* Creates a new {@link AliasingPathBinder} using the given alias and {@link Path}.
|
||||
*
|
||||
*
|
||||
* @param alias can be {@literal null}.
|
||||
* @param path must not be {@literal null}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private AliasingPathBinder(String alias, P path) {
|
||||
|
||||
super(path);
|
||||
@@ -404,7 +420,7 @@ public class QuerydslBindings {
|
||||
* Aliases the current binding to be available under the given path. By default, the binding path will be
|
||||
* blacklisted so that aliasing effectively hides the original path. If you want to keep the original path around,
|
||||
* include it in an explicit whitelist.
|
||||
*
|
||||
*
|
||||
* @param alias must not be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
@@ -418,10 +434,10 @@ public class QuerydslBindings {
|
||||
* Registers the current aliased binding to use the default binding.
|
||||
*/
|
||||
public void withDefaultBinding() {
|
||||
registerBinding(new PathAndBinding<P, T>(path, null));
|
||||
registerBinding(PathAndBinding.withPath(path));
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.binding.QuerydslBindings.PathBinder#registerBinding(org.springframework.data.querydsl.binding.QuerydslBindings.PathAndBinding)
|
||||
*/
|
||||
@@ -450,60 +466,69 @@ public class QuerydslBindings {
|
||||
|
||||
/**
|
||||
* Configures the given {@link SingleValueBinding} to be used for the current type.
|
||||
*
|
||||
*
|
||||
* @param binding must not be {@literal null}.
|
||||
*/
|
||||
public <P extends Path<T>> void firstOptional(OptionalValueBinding<P, T> binding) {
|
||||
|
||||
Assert.notNull(binding, "Binding must not be null!");
|
||||
all(new MultiValueBinding<P, T>() {
|
||||
|
||||
@Override
|
||||
public Optional<Predicate> bind(P path, Collection<? extends T> value) {
|
||||
return binding.bind(path, Optionals.next(value.iterator()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public <P extends Path<T>> void first(SingleValueBinding<P, T> binding) {
|
||||
|
||||
Assert.notNull(binding, "Binding must not be null!");
|
||||
all(new MultiValueBindingAdapter<P, T>(binding));
|
||||
all(new MultiValueBinding<P, T>() {
|
||||
|
||||
@Override
|
||||
public Optional<Predicate> bind(P path, Collection<? extends T> value) {
|
||||
return Optionals.next(value.iterator()).flatMap(t -> binding.bind(path, t));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the given {@link MultiValueBinding} to be used for the current type.
|
||||
*
|
||||
*
|
||||
* @param binding must not be {@literal null}.
|
||||
*/
|
||||
public <P extends Path<T>> void all(MultiValueBinding<P, T> binding) {
|
||||
|
||||
Assert.notNull(binding, "Binding must not be null!");
|
||||
QuerydslBindings.this.typeSpecs.put(type, new PathAndBinding<P, T>(null, binding));
|
||||
|
||||
QuerydslBindings.this.typeSpecs.put(type, PathAndBinding.<T, P> withoutPath().with(binding));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A pair of a {@link Path} and the registered {@link MultiValueBinding}.
|
||||
*
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @since 1.11
|
||||
*/
|
||||
@Value
|
||||
private static class PathAndBinding<S extends Path<? extends T>, T> {
|
||||
private static class PathAndBinding<P extends Path<? extends T>, T> {
|
||||
|
||||
Path<?> path;
|
||||
MultiValueBinding<S, T> binding;
|
||||
}
|
||||
@NonNull Optional<Path<?>> path;
|
||||
@NonNull Optional<MultiValueBinding<P, T>> binding;
|
||||
|
||||
/**
|
||||
* {@link MultiValueBinding} that forwards the first value of the collection values to the delegate
|
||||
* {@link SingleValueBinding}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static class MultiValueBindingAdapter<P extends Path<? extends T>, T> implements MultiValueBinding<P, T> {
|
||||
public static <T, P extends Path<? extends T>> PathAndBinding<P, T> withPath(P path) {
|
||||
return new PathAndBinding<P, T>(Optional.of(path), Optional.empty());
|
||||
}
|
||||
|
||||
private final @NonNull SingleValueBinding<P, T> delegate;
|
||||
public static <T, S extends Path<? extends T>> PathAndBinding<S, T> withoutPath() {
|
||||
return new PathAndBinding<S, T>(Optional.empty(), Optional.empty());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.web.querydsl.MultiValueBinding#bind(com.mysema.query.types.Path, java.util.Collection)
|
||||
*/
|
||||
@Override
|
||||
public Predicate bind(P path, Collection<? extends T> value) {
|
||||
Iterator<? extends T> iterator = value.iterator();
|
||||
return delegate.bind(path, iterator.hasNext() ? iterator.next() : null);
|
||||
public PathAndBinding<P, T> with(MultiValueBinding<P, T> binding) {
|
||||
return new PathAndBinding<P, T>(path, Optional.of(binding));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.querydsl.binding;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -44,8 +45,8 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
|
||||
private final EntityPathResolver entityPathResolver;
|
||||
private final Map<TypeInformation<?>, EntityPath<?>> entityPaths;
|
||||
|
||||
private AutowireCapableBeanFactory beanFactory;
|
||||
private Repositories repositories;
|
||||
private Optional<AutowireCapableBeanFactory> beanFactory;
|
||||
private Optional<Repositories> repositories;
|
||||
|
||||
/**
|
||||
* Creates a new {@link QuerydslBindingsFactory} using the given {@link EntityPathResolver}.
|
||||
@@ -58,6 +59,8 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
|
||||
|
||||
this.entityPathResolver = entityPathResolver;
|
||||
this.entityPaths = new ConcurrentReferenceHashMap<TypeInformation<?>, EntityPath<?>>();
|
||||
this.beanFactory = Optional.empty();
|
||||
this.repositories = Optional.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -67,8 +70,8 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
|
||||
this.beanFactory = applicationContext.getAutowireCapableBeanFactory();
|
||||
this.repositories = new Repositories(applicationContext);
|
||||
this.beanFactory = Optional.of(applicationContext.getAutowireCapableBeanFactory());
|
||||
this.repositories = Optional.of(new Repositories(applicationContext));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,14 +87,15 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
|
||||
* Creates the {@link QuerydslBindings} to be used using for the given domain type and a pre-defined
|
||||
* {@link QuerydslBinderCustomizer}. If no customizer is given, auto-detection will be applied.
|
||||
*
|
||||
* @param customizer the {@link QuerydslBinderCustomizer} to use. If {@literal null} is given customizer detection for
|
||||
* the given domain type will be applied.
|
||||
* @param domainType must not be {@literal null}.
|
||||
* @param customizer the {@link QuerydslBinderCustomizer} to use. If an empty {@link Optional} is given customizer
|
||||
* detection for the given domain type will be applied.
|
||||
* @return
|
||||
*/
|
||||
public QuerydslBindings createBindingsFor(Class<? extends QuerydslBinderCustomizer<?>> customizer,
|
||||
TypeInformation<?> domainType) {
|
||||
public QuerydslBindings createBindingsFor(TypeInformation<?> domainType,
|
||||
Optional<Class<? extends QuerydslBinderCustomizer<?>>> customizer) {
|
||||
|
||||
Assert.notNull(customizer, "Customizer must not be null!");
|
||||
Assert.notNull(domainType, "Domain type must not be null!");
|
||||
|
||||
EntityPath<?> path = verifyEntityPathPresent(domainType);
|
||||
@@ -111,23 +115,15 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
|
||||
*/
|
||||
private EntityPath<?> verifyEntityPathPresent(TypeInformation<?> candidate) {
|
||||
|
||||
EntityPath<?> path = entityPaths.get(candidate);
|
||||
return entityPaths.computeIfAbsent(candidate, key -> {
|
||||
|
||||
if (path != null) {
|
||||
return path;
|
||||
}
|
||||
|
||||
Class<?> type = candidate.getType();
|
||||
|
||||
try {
|
||||
path = entityPathResolver.createPath(type);
|
||||
} catch (IllegalArgumentException o_O) {
|
||||
throw new IllegalStateException(
|
||||
String.format(INVALID_DOMAIN_TYPE, candidate.getType(), QuerydslPredicate.class.getSimpleName()), o_O);
|
||||
}
|
||||
|
||||
entityPaths.put(candidate, path);
|
||||
return path;
|
||||
try {
|
||||
return entityPathResolver.createPath(key.getType());
|
||||
} catch (IllegalArgumentException o_O) {
|
||||
throw new IllegalStateException(
|
||||
String.format(INVALID_DOMAIN_TYPE, key.getType(), QuerydslPredicate.class.getSimpleName()), o_O);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,22 +136,16 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private QuerydslBinderCustomizer<EntityPath<?>> findCustomizerForDomainType(
|
||||
Class<? extends QuerydslBinderCustomizer> customizer, Class<?> domainType) {
|
||||
Optional<? extends Class<? extends QuerydslBinderCustomizer>> customizer, Class<?> domainType) {
|
||||
|
||||
if (customizer != null && !QuerydslBinderCustomizer.class.equals(customizer)) {
|
||||
return createQuerydslBinderCustomizer(customizer);
|
||||
}
|
||||
return customizer//
|
||||
.filter(it -> !QuerydslBinderCustomizer.class.equals(it))//
|
||||
.map(it -> createQuerydslBinderCustomizer(it)).orElseGet(() -> {
|
||||
|
||||
if (repositories != null && repositories.hasRepositoryFor(domainType)) {
|
||||
|
||||
Object repository = repositories.getRepositoryFor(domainType);
|
||||
|
||||
if (repository instanceof QuerydslBinderCustomizer) {
|
||||
return (QuerydslBinderCustomizer<EntityPath<?>>) repository;
|
||||
}
|
||||
}
|
||||
|
||||
return NoOpCustomizer.INSTANCE;
|
||||
return repositories.flatMap(it -> it.getRepositoryFor(domainType))//
|
||||
.map(it -> it instanceof QuerydslBinderCustomizer ? (QuerydslBinderCustomizer<EntityPath<?>>) it : null)//
|
||||
.orElse(NoOpCustomizer.INSTANCE);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,15 +161,14 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
|
||||
private QuerydslBinderCustomizer<EntityPath<?>> createQuerydslBinderCustomizer(
|
||||
Class<? extends QuerydslBinderCustomizer> type) {
|
||||
|
||||
if (beanFactory == null) {
|
||||
return BeanUtils.instantiateClass(type);
|
||||
}
|
||||
return beanFactory.map(it -> {
|
||||
|
||||
try {
|
||||
return beanFactory.getBean(type);
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
return beanFactory.createBean(type);
|
||||
}
|
||||
try {
|
||||
return it.getBean(type);
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
return it.createBean(type);
|
||||
}
|
||||
}).orElseGet(() -> BeanUtils.instantiateClass(type));
|
||||
}
|
||||
|
||||
private static enum NoOpCustomizer implements QuerydslBinderCustomizer<EntityPath<?>> {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.querydsl.binding;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -46,13 +47,13 @@ class QuerydslDefaultBinding implements MultiValueBinding<Path<? extends Object>
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Predicate bind(Path<?> path, Collection<? extends Object> value) {
|
||||
public Optional<Predicate> bind(Path<?> path, Collection<? extends Object> value) {
|
||||
|
||||
Assert.notNull(path, "Path must not be null!");
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
if (value.isEmpty()) {
|
||||
return null;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (path instanceof CollectionPathBase) {
|
||||
@@ -63,16 +64,16 @@ class QuerydslDefaultBinding implements MultiValueBinding<Path<? extends Object>
|
||||
builder.and(((CollectionPathBase) path).contains(element));
|
||||
}
|
||||
|
||||
return builder.getValue();
|
||||
return Optional.of(builder.getValue());
|
||||
}
|
||||
|
||||
if (path instanceof SimpleExpression) {
|
||||
|
||||
if (value.size() > 1) {
|
||||
return ((SimpleExpression) path).in(value);
|
||||
return Optional.of(((SimpleExpression) path).in(value));
|
||||
}
|
||||
|
||||
return ((SimpleExpression) path).eq(value.iterator().next());
|
||||
return Optional.of(((SimpleExpression) path).eq(value.iterator().next()));
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
|
||||
@@ -38,7 +38,7 @@ public @interface QuerydslPredicate {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Class<?>root() default Object.class;
|
||||
Class<?> root() default Object.class;
|
||||
|
||||
/**
|
||||
* To customize the way individual properties' values should be bound to the predicate a
|
||||
@@ -49,5 +49,5 @@ public @interface QuerydslPredicate {
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
Class<? extends QuerydslBinderCustomizer>bindings() default QuerydslBinderCustomizer.class;
|
||||
Class<? extends QuerydslBinderCustomizer> bindings() default QuerydslBinderCustomizer.class;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.PropertyValues;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
@@ -50,7 +51,7 @@ import com.querydsl.core.types.Predicate;
|
||||
public class QuerydslPredicateBuilder {
|
||||
|
||||
private final ConversionService conversionService;
|
||||
private final MultiValueBinding<?, ?> defaultBinding;
|
||||
private final MultiValueBinding<Path<? extends Object>, Object> defaultBinding;
|
||||
private final Map<PathInformation, Path<?>> paths;
|
||||
private final EntityPathResolver resolver;
|
||||
|
||||
@@ -67,7 +68,7 @@ public class QuerydslPredicateBuilder {
|
||||
|
||||
this.defaultBinding = new QuerydslDefaultBinding();
|
||||
this.conversionService = conversionService;
|
||||
this.paths = new HashMap<PathInformation, Path<?>>();
|
||||
this.paths = new HashMap<>();
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
@@ -110,11 +111,9 @@ public class QuerydslPredicateBuilder {
|
||||
}
|
||||
|
||||
Collection<Object> value = convertToPropertyPathSpecificType(entry.getValue(), propertyPath);
|
||||
Predicate predicate = invokeBinding(propertyPath, bindings, value);
|
||||
Optional<Predicate> predicate = invokeBinding(propertyPath, bindings, value);
|
||||
|
||||
if (predicate != null) {
|
||||
builder.and(predicate);
|
||||
}
|
||||
predicate.ifPresent(it -> builder.and(it));
|
||||
}
|
||||
|
||||
return builder.getValue();
|
||||
@@ -128,15 +127,12 @@ public class QuerydslPredicateBuilder {
|
||||
* @param values must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private Predicate invokeBinding(PathInformation dotPath, QuerydslBindings bindings, Collection<Object> values) {
|
||||
private Optional<Predicate> invokeBinding(PathInformation dotPath, QuerydslBindings bindings,
|
||||
Collection<Object> values) {
|
||||
|
||||
Path<?> path = getPath(dotPath, bindings);
|
||||
|
||||
MultiValueBinding binding = bindings.getBindingForPath(dotPath);
|
||||
binding = binding == null ? defaultBinding : binding;
|
||||
|
||||
return binding.bind(path, values);
|
||||
return bindings.getBindingForPath(dotPath).orElse(defaultBinding).bind(path, values);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,22 +146,9 @@ public class QuerydslPredicateBuilder {
|
||||
*/
|
||||
private Path<?> getPath(PathInformation path, QuerydslBindings bindings) {
|
||||
|
||||
Path<?> resolvedPath = bindings.getExistingPath(path);
|
||||
Optional<Path<?>> resolvedPath = bindings.getExistingPath(path);
|
||||
|
||||
if (resolvedPath != null) {
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
resolvedPath = paths.get(resolvedPath);
|
||||
|
||||
if (resolvedPath != null) {
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
resolvedPath = path.reifyPath(resolver);
|
||||
paths.put(path, resolvedPath);
|
||||
|
||||
return resolvedPath;
|
||||
return resolvedPath.orElseGet(() -> paths.computeIfAbsent(path, it -> path.reifyPath(resolver)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.querydsl.binding;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.querydsl.core.types.Path;
|
||||
import com.querydsl.core.types.Predicate;
|
||||
|
||||
@@ -38,5 +40,5 @@ public interface SingleValueBinding<T extends Path<? extends S>, S> {
|
||||
* @return can be {@literal null}, in which case the binding will not be incorporated in the overall {@link Predicate}
|
||||
* .
|
||||
*/
|
||||
Predicate bind(T path, S value);
|
||||
Optional<Predicate> bind(T path, S value);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user