You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2017/04/20 12:00:33 UTC
cayenne git commit: Remove "recursive" generic from FluentSelect and
split back ObjectSelect and ColumnSelect methods. This is a workaround for
static compiling in Groovy that can't handle such generics.
Repository: cayenne
Updated Branches:
refs/heads/master 4e268e756 -> 0e6f0df17
Remove "recursive" generic from FluentSelect and split back ObjectSelect and ColumnSelect methods.
This is a workaround for static compiling in Groovy that can't handle such generics.
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/0e6f0df1
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/0e6f0df1
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/0e6f0df1
Branch: refs/heads/master
Commit: 0e6f0df1714216e3b615e7ed6718693439175a10
Parents: 4e268e7
Author: Nikita Timofeev <st...@gmail.com>
Authored: Thu Apr 20 15:00:27 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Thu Apr 20 15:00:27 2017 +0300
----------------------------------------------------------------------
.../org/apache/cayenne/query/ColumnSelect.java | 331 +++++++++++++++-
.../org/apache/cayenne/query/FluentSelect.java | 391 +------------------
.../org/apache/cayenne/query/ObjectSelect.java | 378 +++++++++++++++++-
3 files changed, 706 insertions(+), 394 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e6f0df1/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
index b0f708c..ca9db48 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
@@ -19,14 +19,19 @@
package org.apache.cayenne.query;
+import java.sql.Statement;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.exp.Property;
+import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjEntity;
/**
* <p>A helper builder for queries selecting individual properties based on the root object.</p>
@@ -55,7 +60,7 @@ import org.apache.cayenne.map.EntityResolver;
*
* @since 4.0
*/
-public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>> {
+public class ColumnSelect<T> extends FluentSelect<T> {
private Collection<Property<?>> columns;
private boolean havingExpressionIsActive = false;
@@ -101,6 +106,323 @@ public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>> {
}
/**
+ * Sets the type of the entity to fetch without changing the return type of
+ * the query.
+ *
+ * @return this object
+ */
+ public ColumnSelect<T> entityType(Class<?> entityType) {
+ return resetEntity(entityType, null, null);
+ }
+
+ /**
+ * Sets the {@link ObjEntity} name to fetch without changing the return type
+ * of the query. This form is most often used for generic entities that
+ * don't map to a distinct class.
+ *
+ * @return this object
+ */
+ public ColumnSelect<T> entityName(String entityName) {
+ return resetEntity(null, entityName, null);
+ }
+
+ /**
+ * Sets the {@link DbEntity} name to fetch without changing the return type
+ * of the query. This form is most often used for generic entities that
+ * don't map to a distinct class.
+ *
+ * @return this object
+ */
+ public ColumnSelect<T> dbEntityName(String dbEntityName) {
+ return resetEntity(null, null, dbEntityName);
+ }
+
+ @SuppressWarnings("unchecked")
+ private ColumnSelect<T> resetEntity(Class<?> entityType, String entityName, String dbEntityName) {
+ this.entityType = entityType;
+ this.entityName = entityName;
+ this.dbEntityName = dbEntityName;
+ return (ColumnSelect<T>)this;
+ }
+
+ /**
+ * Appends a qualifier expression of this query. An equivalent to
+ * {@link #and(Expression...)} that can be used a syntactic sugar.
+ *
+ * @return this object
+ */
+ public ColumnSelect<T> where(Expression expression) {
+ return and(expression);
+ }
+
+ /**
+ * Appends a qualifier expression of this query, using provided expression
+ * String and an array of position parameters. This is an equivalent to
+ * calling "and".
+ *
+ * @return this object
+ */
+ public ColumnSelect<T> where(String expressionString, Object... parameters) {
+ return and(ExpressionFactory.exp(expressionString, parameters));
+ }
+
+ /**
+ * AND's provided expressions to the existing WHERE clause expression.
+ *
+ * @return this object
+ */
+ public ColumnSelect<T> and(Expression... expressions) {
+ if (expressions == null || expressions.length == 0) {
+ return this;
+ }
+
+ return and(Arrays.asList(expressions));
+ }
+
+ /**
+ * OR's provided expressions to the existing WHERE clause expression.
+ *
+ * @return this object
+ */
+ @SuppressWarnings("unchecked")
+ public ColumnSelect<T> or(Expression... expressions) {
+ if (expressions == null || expressions.length == 0) {
+ return this;
+ }
+
+ return or(Arrays.asList(expressions));
+ }
+
+ /**
+ * Add an ascending ordering on the given property. If there is already an ordering
+ * on this query then add this ordering with a lower priority.
+ *
+ * @param property the property to sort on
+ * @return this object
+ */
+ public ColumnSelect<T> orderBy(String property) {
+ return orderBy(new Ordering(property));
+ }
+
+ /**
+ * Add an ordering on the given property. If there is already an ordering
+ * on this query then add this ordering with a lower priority.
+ *
+ * @param property the property to sort on
+ * @param sortOrder the direction of the ordering
+ * @return this object
+ */
+ public ColumnSelect<T> orderBy(String property, SortOrder sortOrder) {
+ return orderBy(new Ordering(property, sortOrder));
+ }
+
+ /**
+ * Add one or more orderings to this query.
+ *
+ * @return this object
+ */
+ public ColumnSelect<T> orderBy(Ordering... orderings) {
+
+ if (orderings == null) {
+ return this;
+ }
+
+ if (this.orderings == null) {
+ this.orderings = new ArrayList<>(orderings.length);
+ }
+
+ Collections.addAll(this.orderings, orderings);
+
+ return this;
+ }
+
+ /**
+ * Adds a list of orderings to this query.
+ *
+ * @return this object
+ */
+ public ColumnSelect<T> orderBy(Collection<Ordering> orderings) {
+
+ if (orderings == null) {
+ return this;
+ }
+
+ if (this.orderings == null) {
+ this.orderings = new ArrayList<>(orderings.size());
+ }
+
+ this.orderings.addAll(orderings);
+
+ return this;
+ }
+
+ /**
+ * Merges prefetch into the query prefetch tree.
+ *
+ * @return this object
+ */
+ public ColumnSelect<T> prefetch(PrefetchTreeNode prefetch) {
+
+ if (prefetch == null) {
+ return this;
+ }
+
+ if (prefetches == null) {
+ prefetches = new PrefetchTreeNode();
+ }
+
+ prefetches.merge(prefetch);
+ return this;
+ }
+
+ /**
+ * Merges a prefetch path with specified semantics into the query prefetch
+ * tree.
+ *
+ * @return this object
+ */
+ public ColumnSelect<T> prefetch(String path, int semantics) {
+
+ if (path == null) {
+ return this;
+ }
+
+ if (prefetches == null) {
+ prefetches = new PrefetchTreeNode();
+ }
+
+ prefetches.addPath(path).setSemantics(semantics);
+ return this;
+ }
+
+ /**
+ * Resets query fetch limit - a parameter that defines max number of objects
+ * that should be ever be fetched from the database.
+ */
+ public ColumnSelect<T> limit(int fetchLimit) {
+ if (this.limit != fetchLimit) {
+ this.limit = fetchLimit;
+ this.replacementQuery = null;
+ }
+
+ return this;
+ }
+
+ /**
+ * Resets query fetch offset - a parameter that defines how many objects
+ * should be skipped when reading data from the database.
+ */
+ public ColumnSelect<T> offset(int fetchOffset) {
+ if (this.offset != fetchOffset) {
+ this.offset = fetchOffset;
+ this.replacementQuery = null;
+ }
+
+ return this;
+ }
+
+ /**
+ * Resets query page size. A non-negative page size enables query result
+ * pagination that saves memory and processing time for large lists if only
+ * parts of the result are ever going to be accessed.
+ */
+ public ColumnSelect<T> pageSize(int pageSize) {
+ if (this.pageSize != pageSize) {
+ this.pageSize = pageSize;
+ this.replacementQuery = null;
+ }
+
+ return this;
+ }
+
+ /**
+ * Sets fetch size of the PreparedStatement generated for this query. Only
+ * non-negative values would change the default size.
+ *
+ * @see Statement#setFetchSize(int)
+ */
+ public ColumnSelect<T> statementFetchSize(int size) {
+ if (this.statementFetchSize != size) {
+ this.statementFetchSize = size;
+ this.replacementQuery = null;
+ }
+
+ return this;
+ }
+
+ public ColumnSelect<T> cacheStrategy(QueryCacheStrategy strategy) {
+ if (this.cacheStrategy != strategy) {
+ this.cacheStrategy = strategy;
+ this.replacementQuery = null;
+ }
+
+ if(this.cacheGroup != null) {
+ this.cacheGroup = null;
+ this.replacementQuery = null;
+ }
+
+ return this;
+ }
+
+ public ColumnSelect<T> cacheStrategy(QueryCacheStrategy strategy, String cacheGroup) {
+ return cacheStrategy(strategy).cacheGroup(cacheGroup);
+ }
+
+ public ColumnSelect<T> cacheGroup(String cacheGroup) {
+ this.cacheGroup = cacheGroup;
+ this.replacementQuery = null;
+ return this;
+ }
+
+ /**
+ * Instructs Cayenne to look for query results in the "local" cache when
+ * running the query. This is a short-hand notation for:
+ * <p>
+ * <pre>
+ * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
+ * </pre>
+ */
+ public ColumnSelect<T> localCache(String cacheGroup) {
+ return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
+ }
+
+ /**
+ * Instructs Cayenne to look for query results in the "local" cache when
+ * running the query. This is a short-hand notation for:
+ * <p>
+ * <pre>
+ * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+ * </pre>
+ */
+ public ColumnSelect<T> localCache() {
+ return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+ }
+
+ /**
+ * Instructs Cayenne to look for query results in the "shared" cache when
+ * running the query. This is a short-hand notation for:
+ * <p>
+ * <pre>
+ * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
+ * </pre>
+ */
+ public ColumnSelect<T> sharedCache(String cacheGroup) {
+ return cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
+ }
+
+ /**
+ * Instructs Cayenne to look for query results in the "shared" cache when
+ * running the query. This is a short-hand notation for:
+ * <p>
+ * <pre>
+ * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+ * </pre>
+ */
+ public ColumnSelect<T> sharedCache() {
+ return cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+ }
+
+ /**
* <p>Add properties to select.</p>
* <p>Can be any properties that can be resolved against root entity type
* (root entity properties, function call expressions, properties of relationships, etc).</p>
@@ -242,7 +564,6 @@ public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>> {
*
* @return this object
*/
- @SuppressWarnings("unchecked")
public ColumnSelect<T> and(Collection<Expression> expressions) {
if (expressions == null || expressions.isEmpty()) {
@@ -269,7 +590,6 @@ public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>> {
*
* @return this object
*/
- @SuppressWarnings("unchecked")
public ColumnSelect<T> or(Collection<Expression> expressions) {
if (expressions == null || expressions.isEmpty()) {
return this;
@@ -334,4 +654,9 @@ public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>> {
public Expression getHaving() {
return having;
}
+
+ @Override
+ public T selectFirst(ObjectContext context) {
+ return context.selectFirst(limit(1));
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e6f0df1/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java
index 91204af..8f2360c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java
@@ -19,11 +19,7 @@
package org.apache.cayenne.query;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import org.apache.cayenne.CayenneRuntimeException;
@@ -32,7 +28,6 @@ import org.apache.cayenne.ResultBatchIterator;
import org.apache.cayenne.ResultIterator;
import org.apache.cayenne.ResultIteratorCallback;
import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.ObjEntity;
@@ -42,7 +37,7 @@ import org.apache.cayenne.map.ObjEntity;
*
* @since 4.0
*/
-public abstract class FluentSelect<T, S extends FluentSelect<T, S>> extends IndirectQuery implements Select<T> {
+public abstract class FluentSelect<T> extends IndirectQuery implements Select<T> {
protected Class<?> entityType;
protected String entityName;
@@ -106,385 +101,6 @@ public abstract class FluentSelect<T, S extends FluentSelect<T, S>> extends Indi
return replacement;
}
- /**
- * Sets the type of the entity to fetch without changing the return type of
- * the query.
- *
- * @return this object
- */
- public S entityType(Class<?> entityType) {
- return resetEntity(entityType, null, null);
- }
-
- /**
- * Sets the {@link ObjEntity} name to fetch without changing the return type
- * of the query. This form is most often used for generic entities that
- * don't map to a distinct class.
- *
- * @return this object
- */
- public S entityName(String entityName) {
- return resetEntity(null, entityName, null);
- }
-
- /**
- * Sets the {@link DbEntity} name to fetch without changing the return type
- * of the query. This form is most often used for generic entities that
- * don't map to a distinct class.
- *
- * @return this object
- */
- public S dbEntityName(String dbEntityName) {
- return resetEntity(null, null, dbEntityName);
- }
-
- @SuppressWarnings("unchecked")
- private S resetEntity(Class<?> entityType, String entityName, String dbEntityName) {
- this.entityType = entityType;
- this.entityName = entityName;
- this.dbEntityName = dbEntityName;
- return (S)this;
- }
-
- /**
- * Appends a qualifier expression of this query. An equivalent to
- * {@link #and(Expression...)} that can be used a syntactic sugar.
- *
- * @return this object
- */
- public S where(Expression expression) {
- return and(expression);
- }
-
- /**
- * Appends a qualifier expression of this query, using provided expression
- * String and an array of position parameters. This is an equivalent to
- * calling "and".
- *
- * @return this object
- */
- public S where(String expressionString, Object... parameters) {
- return and(ExpressionFactory.exp(expressionString, parameters));
- }
-
- /**
- * AND's provided expressions to the existing WHERE clause expression.
- *
- * @return this object
- */
- @SuppressWarnings("unchecked")
- public S and(Expression... expressions) {
- if (expressions == null || expressions.length == 0) {
- return (S)this;
- }
-
- return and(Arrays.asList(expressions));
- }
-
- /**
- * AND's provided expressions to the existing WHERE clause expression.
- *
- * @return this object
- */
- @SuppressWarnings("unchecked")
- public S and(Collection<Expression> expressions) {
-
- if (expressions == null || expressions.isEmpty()) {
- return (S)this;
- }
-
- Collection<Expression> all;
-
- if (where != null) {
- all = new ArrayList<>(expressions.size() + 1);
- all.add(where);
- all.addAll(expressions);
- } else {
- all = expressions;
- }
-
- where = ExpressionFactory.and(all);
- return (S)this;
- }
-
- /**
- * OR's provided expressions to the existing WHERE clause expression.
- *
- * @return this object
- */
- @SuppressWarnings("unchecked")
- public S or(Expression... expressions) {
- if (expressions == null || expressions.length == 0) {
- return (S)this;
- }
-
- return or(Arrays.asList(expressions));
- }
-
- /**
- * OR's provided expressions to the existing WHERE clause expression.
- *
- * @return this object
- */
- @SuppressWarnings("unchecked")
- public S or(Collection<Expression> expressions) {
- if (expressions == null || expressions.isEmpty()) {
- return (S)this;
- }
-
- Collection<Expression> all;
-
- if (where != null) {
- all = new ArrayList<>(expressions.size() + 1);
- all.add(where);
- all.addAll(expressions);
- } else {
- all = expressions;
- }
-
- where = ExpressionFactory.or(all);
- return (S)this;
- }
-
- /**
- * Add an ascending ordering on the given property. If there is already an ordering
- * on this query then add this ordering with a lower priority.
- *
- * @param property the property to sort on
- * @return this object
- */
- public S orderBy(String property) {
- return orderBy(new Ordering(property));
- }
-
- /**
- * Add an ordering on the given property. If there is already an ordering
- * on this query then add this ordering with a lower priority.
- *
- * @param property the property to sort on
- * @param sortOrder the direction of the ordering
- * @return this object
- */
- public S orderBy(String property, SortOrder sortOrder) {
- return orderBy(new Ordering(property, sortOrder));
- }
-
- /**
- * Add one or more orderings to this query.
- *
- * @return this object
- */
- @SuppressWarnings("unchecked")
- public S orderBy(Ordering... orderings) {
-
- if (orderings == null) {
- return (S)this;
- }
-
- if (this.orderings == null) {
- this.orderings = new ArrayList<>(orderings.length);
- }
-
- Collections.addAll(this.orderings, orderings);
-
- return (S)this;
- }
-
- /**
- * Adds a list of orderings to this query.
- *
- * @return this object
- */
- @SuppressWarnings("unchecked")
- public S orderBy(Collection<Ordering> orderings) {
-
- if (orderings == null) {
- return (S)this;
- }
-
- if (this.orderings == null) {
- this.orderings = new ArrayList<>(orderings.size());
- }
-
- this.orderings.addAll(orderings);
-
- return (S)this;
- }
-
- /**
- * Merges prefetch into the query prefetch tree.
- *
- * @return this object
- */
- @SuppressWarnings("unchecked")
- public S prefetch(PrefetchTreeNode prefetch) {
-
- if (prefetch == null) {
- return (S)this;
- }
-
- if (prefetches == null) {
- prefetches = new PrefetchTreeNode();
- }
-
- prefetches.merge(prefetch);
- return (S)this;
- }
-
- /**
- * Merges a prefetch path with specified semantics into the query prefetch
- * tree.
- *
- * @return this object
- */
- @SuppressWarnings("unchecked")
- public S prefetch(String path, int semantics) {
-
- if (path == null) {
- return (S)this;
- }
-
- if (prefetches == null) {
- prefetches = new PrefetchTreeNode();
- }
-
- prefetches.addPath(path).setSemantics(semantics);
- return (S)this;
- }
-
- /**
- * Resets query fetch limit - a parameter that defines max number of objects
- * that should be ever be fetched from the database.
- */
- @SuppressWarnings("unchecked")
- public S limit(int fetchLimit) {
- if (this.limit != fetchLimit) {
- this.limit = fetchLimit;
- this.replacementQuery = null;
- }
-
- return (S)this;
- }
-
- /**
- * Resets query fetch offset - a parameter that defines how many objects
- * should be skipped when reading data from the database.
- */
- @SuppressWarnings("unchecked")
- public S offset(int fetchOffset) {
- if (this.offset != fetchOffset) {
- this.offset = fetchOffset;
- this.replacementQuery = null;
- }
-
- return (S)this;
- }
-
- /**
- * Resets query page size. A non-negative page size enables query result
- * pagination that saves memory and processing time for large lists if only
- * parts of the result are ever going to be accessed.
- */
- @SuppressWarnings("unchecked")
- public S pageSize(int pageSize) {
- if (this.pageSize != pageSize) {
- this.pageSize = pageSize;
- this.replacementQuery = null;
- }
-
- return (S)this;
- }
-
- /**
- * Sets fetch size of the PreparedStatement generated for this query. Only
- * non-negative values would change the default size.
- *
- * @see Statement#setFetchSize(int)
- */
- @SuppressWarnings("unchecked")
- public S statementFetchSize(int size) {
- if (this.statementFetchSize != size) {
- this.statementFetchSize = size;
- this.replacementQuery = null;
- }
-
- return (S)this;
- }
-
- @SuppressWarnings("unchecked")
- public S cacheStrategy(QueryCacheStrategy strategy) {
- if (this.cacheStrategy != strategy) {
- this.cacheStrategy = strategy;
- this.replacementQuery = null;
- }
-
- if(this.cacheGroup != null) {
- this.cacheGroup = null;
- this.replacementQuery = null;
- }
-
- return (S)this;
- }
-
- public S cacheStrategy(QueryCacheStrategy strategy, String cacheGroup) {
- return cacheStrategy(strategy).cacheGroup(cacheGroup);
- }
-
- @SuppressWarnings("unchecked")
- public S cacheGroup(String cacheGroup) {
- this.cacheGroup = cacheGroup;
- this.replacementQuery = null;
- return (S)this;
- }
-
- /**
- * Instructs Cayenne to look for query results in the "local" cache when
- * running the query. This is a short-hand notation for:
- * <p>
- * <pre>
- * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
- * </pre>
- */
- public S localCache(String cacheGroup) {
- return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
- }
-
- /**
- * Instructs Cayenne to look for query results in the "local" cache when
- * running the query. This is a short-hand notation for:
- * <p>
- * <pre>
- * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
- * </pre>
- */
- public S localCache() {
- return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
- }
-
- /**
- * Instructs Cayenne to look for query results in the "shared" cache when
- * running the query. This is a short-hand notation for:
- * <p>
- * <pre>
- * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
- * </pre>
- */
- public S sharedCache(String cacheGroup) {
- return cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
- }
-
- /**
- * Instructs Cayenne to look for query results in the "shared" cache when
- * running the query. This is a short-hand notation for:
- * <p>
- * <pre>
- * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
- * </pre>
- */
- public S sharedCache() {
- return cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
- }
-
public String getCacheGroup() {
return cacheGroup;
}
@@ -547,11 +163,6 @@ public abstract class FluentSelect<T, S extends FluentSelect<T, S>> extends Indi
}
@Override
- public T selectFirst(ObjectContext context) {
- return context.selectFirst(limit(1));
- }
-
- @Override
public void iterate(ObjectContext context, ResultIteratorCallback<T> callback) {
context.iterate(this, callback);
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e6f0df1/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java
index da03ccb..a37cf37 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java
@@ -21,11 +21,17 @@ package org.apache.cayenne.query;
import org.apache.cayenne.DataRow;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.exp.Property;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.ObjEntity;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
@@ -43,7 +49,7 @@ import java.util.List;
*
* @since 4.0
*/
-public class ObjectSelect<T> extends FluentSelect<T, ObjectSelect<T>> {
+public class ObjectSelect<T> extends FluentSelect<T> {
private static final long serialVersionUID = -156124021150949227L;
@@ -155,6 +161,371 @@ public class ObjectSelect<T> extends FluentSelect<T, ObjectSelect<T>> {
}
/**
+ * Sets the type of the entity to fetch without changing the return type of
+ * the query.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> entityType(Class<?> entityType) {
+ return resetEntity(entityType, null, null);
+ }
+
+ /**
+ * Sets the {@link ObjEntity} name to fetch without changing the return type
+ * of the query. This form is most often used for generic entities that
+ * don't map to a distinct class.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> entityName(String entityName) {
+ return resetEntity(null, entityName, null);
+ }
+
+ /**
+ * Sets the {@link DbEntity} name to fetch without changing the return type
+ * of the query. This form is most often used for generic entities that
+ * don't map to a distinct class.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> dbEntityName(String dbEntityName) {
+ return resetEntity(null, null, dbEntityName);
+ }
+
+ private ObjectSelect<T> resetEntity(Class<?> entityType, String entityName, String dbEntityName) {
+ this.entityType = entityType;
+ this.entityName = entityName;
+ this.dbEntityName = dbEntityName;
+ return this;
+ }
+
+ /**
+ * Appends a qualifier expression of this query. An equivalent to
+ * {@link #and(Expression...)} that can be used a syntactic sugar.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> where(Expression expression) {
+ return and(expression);
+ }
+
+ /**
+ * Appends a qualifier expression of this query, using provided expression
+ * String and an array of position parameters. This is an equivalent to
+ * calling "and".
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> where(String expressionString, Object... parameters) {
+ return and(ExpressionFactory.exp(expressionString, parameters));
+ }
+
+ /**
+ * AND's provided expressions to the existing WHERE clause expression.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> and(Expression... expressions) {
+ if (expressions == null || expressions.length == 0) {
+ return this;
+ }
+
+ return and(Arrays.asList(expressions));
+ }
+
+ /**
+ * AND's provided expressions to the existing WHERE clause expression.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> and(Collection<Expression> expressions) {
+
+ if (expressions == null || expressions.isEmpty()) {
+ return this;
+ }
+
+ Collection<Expression> all;
+
+ if (where != null) {
+ all = new ArrayList<>(expressions.size() + 1);
+ all.add(where);
+ all.addAll(expressions);
+ } else {
+ all = expressions;
+ }
+
+ where = ExpressionFactory.and(all);
+ return this;
+ }
+
+ /**
+ * OR's provided expressions to the existing WHERE clause expression.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> or(Expression... expressions) {
+ if (expressions == null || expressions.length == 0) {
+ return this;
+ }
+
+ return or(Arrays.asList(expressions));
+ }
+
+ /**
+ * OR's provided expressions to the existing WHERE clause expression.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> or(Collection<Expression> expressions) {
+ if (expressions == null || expressions.isEmpty()) {
+ return this;
+ }
+
+ Collection<Expression> all;
+
+ if (where != null) {
+ all = new ArrayList<>(expressions.size() + 1);
+ all.add(where);
+ all.addAll(expressions);
+ } else {
+ all = expressions;
+ }
+
+ where = ExpressionFactory.or(all);
+ return this;
+ }
+
+ /**
+ * Add an ascending ordering on the given property. If there is already an ordering
+ * on this query then add this ordering with a lower priority.
+ *
+ * @param property the property to sort on
+ * @return this object
+ */
+ public ObjectSelect<T> orderBy(String property) {
+ return orderBy(new Ordering(property));
+ }
+
+ /**
+ * Add an ordering on the given property. If there is already an ordering
+ * on this query then add this ordering with a lower priority.
+ *
+ * @param property the property to sort on
+ * @param sortOrder the direction of the ordering
+ * @return this object
+ */
+ public ObjectSelect<T> orderBy(String property, SortOrder sortOrder) {
+ return orderBy(new Ordering(property, sortOrder));
+ }
+
+ /**
+ * Add one or more orderings to this query.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> orderBy(Ordering... orderings) {
+
+ if (orderings == null) {
+ return this;
+ }
+
+ if (this.orderings == null) {
+ this.orderings = new ArrayList<>(orderings.length);
+ }
+
+ Collections.addAll(this.orderings, orderings);
+
+ return this;
+ }
+
+ /**
+ * Adds a list of orderings to this query.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> orderBy(Collection<Ordering> orderings) {
+
+ if (orderings == null) {
+ return this;
+ }
+
+ if (this.orderings == null) {
+ this.orderings = new ArrayList<>(orderings.size());
+ }
+
+ this.orderings.addAll(orderings);
+
+ return this;
+ }
+
+ /**
+ * Merges prefetch into the query prefetch tree.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> prefetch(PrefetchTreeNode prefetch) {
+
+ if (prefetch == null) {
+ return this;
+ }
+
+ if (prefetches == null) {
+ prefetches = new PrefetchTreeNode();
+ }
+
+ prefetches.merge(prefetch);
+ return this;
+ }
+
+ /**
+ * Merges a prefetch path with specified semantics into the query prefetch
+ * tree.
+ *
+ * @return this object
+ */
+ public ObjectSelect<T> prefetch(String path, int semantics) {
+
+ if (path == null) {
+ return this;
+ }
+
+ if (prefetches == null) {
+ prefetches = new PrefetchTreeNode();
+ }
+
+ prefetches.addPath(path).setSemantics(semantics);
+ return this;
+ }
+
+ /**
+ * Resets query fetch limit - a parameter that defines max number of objects
+ * that should be ever be fetched from the database.
+ */
+ @SuppressWarnings("unchecked")
+ public ObjectSelect<T> limit(int fetchLimit) {
+ if (this.limit != fetchLimit) {
+ this.limit = fetchLimit;
+ this.replacementQuery = null;
+ }
+
+ return this;
+ }
+
+ /**
+ * Resets query fetch offset - a parameter that defines how many objects
+ * should be skipped when reading data from the database.
+ */
+ public ObjectSelect<T> offset(int fetchOffset) {
+ if (this.offset != fetchOffset) {
+ this.offset = fetchOffset;
+ this.replacementQuery = null;
+ }
+
+ return this;
+ }
+
+ /**
+ * Resets query page size. A non-negative page size enables query result
+ * pagination that saves memory and processing time for large lists if only
+ * parts of the result are ever going to be accessed.
+ */
+ public ObjectSelect<T> pageSize(int pageSize) {
+ if (this.pageSize != pageSize) {
+ this.pageSize = pageSize;
+ this.replacementQuery = null;
+ }
+
+ return this;
+ }
+
+ /**
+ * Sets fetch size of the PreparedStatement generated for this query. Only
+ * non-negative values would change the default size.
+ *
+ * @see Statement#setFetchSize(int)
+ */
+ public ObjectSelect<T> statementFetchSize(int size) {
+ if (this.statementFetchSize != size) {
+ this.statementFetchSize = size;
+ this.replacementQuery = null;
+ }
+
+ return this;
+ }
+
+ public ObjectSelect<T> cacheStrategy(QueryCacheStrategy strategy) {
+ if (this.cacheStrategy != strategy) {
+ this.cacheStrategy = strategy;
+ this.replacementQuery = null;
+ }
+
+ if(this.cacheGroup != null) {
+ this.cacheGroup = null;
+ this.replacementQuery = null;
+ }
+
+ return this;
+ }
+
+ public ObjectSelect<T> cacheStrategy(QueryCacheStrategy strategy, String cacheGroup) {
+ return cacheStrategy(strategy).cacheGroup(cacheGroup);
+ }
+
+ public ObjectSelect<T> cacheGroup(String cacheGroup) {
+ this.cacheGroup = cacheGroup;
+ this.replacementQuery = null;
+ return this;
+ }
+
+ /**
+ * Instructs Cayenne to look for query results in the "local" cache when
+ * running the query. This is a short-hand notation for:
+ * <p>
+ * <pre>
+ * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
+ * </pre>
+ */
+ public ObjectSelect<T> localCache(String cacheGroup) {
+ return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
+ }
+
+ /**
+ * Instructs Cayenne to look for query results in the "local" cache when
+ * running the query. This is a short-hand notation for:
+ * <p>
+ * <pre>
+ * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+ * </pre>
+ */
+ public ObjectSelect<T> localCache() {
+ return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+ }
+
+ /**
+ * Instructs Cayenne to look for query results in the "shared" cache when
+ * running the query. This is a short-hand notation for:
+ * <p>
+ * <pre>
+ * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
+ * </pre>
+ */
+ public ObjectSelect<T> sharedCache(String cacheGroup) {
+ return cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
+ }
+
+ /**
+ * Instructs Cayenne to look for query results in the "shared" cache when
+ * running the query. This is a short-hand notation for:
+ * <p>
+ * <pre>
+ * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+ * </pre>
+ */
+ public ObjectSelect<T> sharedCache() {
+ return cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+ }
+
+ /**
* Forces query to fetch DataRows. This automatically changes whatever
* result type was set previously to "DataRow".
*
@@ -275,6 +646,11 @@ public class ObjectSelect<T> extends FluentSelect<T, ObjectSelect<T>> {
return count().selectOne(context);
}
+ @Override
+ public T selectFirst(ObjectContext context) {
+ return context.selectFirst(limit(1));
+ }
+
public boolean isFetchingDataRows() {
return fetchingDataRows;
}