DATAJPA-71 - Tweaked AbstractQueryCreator to be more flexible.
AbstractQueryCreator is now more lenient. We're now allowing instantiation without a ParameterAccessor for implementations that don't want to do parameter binding during query creation. We additionally provide a createQuery(Sort) now to allow handing in a dynamic Sort parameter taken from a query method to apply sorting even in case we don't bind parameters directly. Added a method to Parameters to discover whether we potentially sort dynamically which simply tests for a Sort or Pageable parameter in the method signature.
This commit is contained in:
@@ -183,6 +183,17 @@ public final class Parameters implements Iterable<Parameter> {
|
||||
|
||||
return sortIndex != -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether we potentially find a {@link Sort} parameter in the parameters.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean potentiallySortsDynamically() {
|
||||
|
||||
return hasSortParameter() || hasPageableParameter();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,11 +23,9 @@ import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.parser.PartTree.OrPart;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Base class for query creators that create criteria based queries from a
|
||||
* {@link PartTree}.
|
||||
*
|
||||
* Base class for query creators that create criteria based queries from a {@link PartTree}.
|
||||
*
|
||||
* @param T the actual query type to be created
|
||||
* @param S the intermediate criteria type
|
||||
* @author Oliver Gierke
|
||||
@@ -43,43 +41,62 @@ public abstract class AbstractQueryCreator<T, S> {
|
||||
* via a {@link Sort} parameter.
|
||||
*
|
||||
* @param tree must not be {@literal null}.
|
||||
* @param parameters
|
||||
* @param parameters can be {@literal null}.
|
||||
*/
|
||||
public AbstractQueryCreator(PartTree tree, ParameterAccessor parameters) {
|
||||
|
||||
Assert.notNull(tree);
|
||||
Assert.notNull(parameters);
|
||||
|
||||
this.tree = tree;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractQueryCreator} for the given {@link PartTree}. This will cause {@literal null} be
|
||||
* handed for the {@link Iterator} in the callback methods.
|
||||
*
|
||||
* @param tree must not be {@literal null}.
|
||||
*/
|
||||
public AbstractQueryCreator(PartTree tree) {
|
||||
|
||||
this(tree, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the actual query object.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public T createQuery() {
|
||||
|
||||
Sort treeSort = tree.getSort();
|
||||
Sort sort = treeSort != null ? treeSort : parameters.getSort();
|
||||
Sort dynamicSort = parameters != null ? parameters.getSort() : null;
|
||||
return createQuery(dynamicSort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the actual query object applying the given {@link Sort} parameter. Use this method in case you haven't
|
||||
* provided a {@link ParameterAccessor} in the first place but want to apply dynamic sorting nevertheless.
|
||||
*
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
public T createQuery(Sort sort) {
|
||||
|
||||
return complete(createCriteria(tree), sort);
|
||||
Sort sortToUse = sort != null ? sort : tree.getSort();
|
||||
return complete(createCriteria(tree), sortToUse);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Actual query building logic. Traverses the {@link PartTree} and invokes
|
||||
* callback methods to delegate actual criteria creation and concatenation.
|
||||
*
|
||||
* Actual query building logic. Traverses the {@link PartTree} and invokes callback methods to delegate actual
|
||||
* criteria creation and concatenation.
|
||||
*
|
||||
* @param tree
|
||||
* @return
|
||||
*/
|
||||
private S createCriteria(PartTree tree) {
|
||||
|
||||
S base = null;
|
||||
Iterator<Object> iterator = parameters.iterator();
|
||||
Iterator<Object> iterator = parameters == null ? null : parameters.iterator();
|
||||
|
||||
for (OrPart node : tree) {
|
||||
|
||||
@@ -87,9 +104,7 @@ public abstract class AbstractQueryCreator<T, S> {
|
||||
|
||||
for (Part part : node) {
|
||||
|
||||
criteria =
|
||||
criteria == null ? create(part, iterator) : and(part,
|
||||
criteria, iterator);
|
||||
criteria = criteria == null ? create(part, iterator) : and(part, criteria, iterator);
|
||||
}
|
||||
|
||||
base = base == null ? criteria : or(base, criteria);
|
||||
@@ -98,43 +113,37 @@ public abstract class AbstractQueryCreator<T, S> {
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new atomic instance of the criteria object.
|
||||
*
|
||||
*
|
||||
* @param part
|
||||
* @param iterator
|
||||
* @return
|
||||
*/
|
||||
protected abstract S create(Part part, Iterator<Object> iterator);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new criteria object from the given part and and-concatenates it
|
||||
* to the given base criteria.
|
||||
*
|
||||
* Creates a new criteria object from the given part and and-concatenates it to the given base criteria.
|
||||
*
|
||||
* @param part
|
||||
* @param base will never be {@literal null}.
|
||||
* @param base will never be {@literal null}.
|
||||
* @param iterator
|
||||
* @return
|
||||
*/
|
||||
protected abstract S and(Part part, S base, Iterator<Object> iterator);
|
||||
|
||||
|
||||
/**
|
||||
* Or-concatenates the given base criteria to the given new criteria.
|
||||
*
|
||||
*
|
||||
* @param base
|
||||
* @param criteria
|
||||
* @return
|
||||
*/
|
||||
protected abstract S or(S base, S criteria);
|
||||
|
||||
|
||||
/**
|
||||
* Actually creates the query object applying the given criteria object and
|
||||
* {@link Sort} definition.
|
||||
*
|
||||
* Actually creates the query object applying the given criteria object and {@link Sort} definition.
|
||||
*
|
||||
* @param criteria
|
||||
* @param sort
|
||||
* @return
|
||||
|
||||
Reference in New Issue
Block a user