From 751ca2ae221149b91942178c5e1bbe250b27bddc Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 19 Jul 2011 08:40:19 +0200 Subject: [PATCH] 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. --- .../data/repository/query/Parameters.java | 11 +++ .../query/parser/AbstractQueryCreator.java | 71 +++++++++++-------- 2 files changed, 51 insertions(+), 31 deletions(-) diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameters.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameters.java index 39bfa4e67..bf0d3c59d 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameters.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/Parameters.java @@ -183,6 +183,17 @@ public final class Parameters implements Iterable { return sortIndex != -1; } + + + /** + * Returns whether we potentially find a {@link Sort} parameter in the parameters. + * + * @return + */ + public boolean potentiallySortsDynamically() { + + return hasSortParameter() || hasPageableParameter(); + } /** diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/parser/AbstractQueryCreator.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/parser/AbstractQueryCreator.java index 54bd6339b..bfc34369f 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/parser/AbstractQueryCreator.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/parser/AbstractQueryCreator.java @@ -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 { * 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 iterator = parameters.iterator(); + Iterator iterator = parameters == null ? null : parameters.iterator(); for (OrPart node : tree) { @@ -87,9 +104,7 @@ public abstract class AbstractQueryCreator { 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 { return base; } - /** * Creates a new atomic instance of the criteria object. - * + * * @param part * @param iterator * @return */ protected abstract S create(Part part, Iterator 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 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