You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by sk...@apache.org on 2015/04/03 17:28:42 UTC
cayenne git commit: CAY-1995 | Add selectFirst() to Select and
ObjectContext
Repository: cayenne
Updated Branches:
refs/heads/master c38a8e6b8 -> 44fdc8454
CAY-1995 | Add selectFirst() to Select and ObjectContext
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/44fdc845
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/44fdc845
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/44fdc845
Branch: refs/heads/master
Commit: 44fdc8454b949d665e1b79068e0f31d4967c8d6f
Parents: c38a8e6
Author: Savva Kolbachev <s....@gmail.com>
Authored: Fri Apr 3 18:27:42 2015 +0300
Committer: Savva Kolbachev <s....@gmail.com>
Committed: Fri Apr 3 18:27:42 2015 +0300
----------------------------------------------------------------------
.../java/org/apache/cayenne/BaseContext.java | 24 ++++++++++++++------
.../java/org/apache/cayenne/ObjectContext.java | 19 ++++++++++++++++
.../org/apache/cayenne/query/ObjectSelect.java | 22 ++++--------------
.../org/apache/cayenne/query/SQLSelect.java | 22 ++++--------------
.../java/org/apache/cayenne/query/Select.java | 24 ++++++++++++++++++++
.../org/apache/cayenne/query/SelectById.java | 9 ++++++++
.../org/apache/cayenne/query/SelectQuery.java | 6 +++++
.../cayenne/remote/IncrementalSelectQuery.java | 5 ++++
.../cayenne/query/ObjectSelect_RunIT.java | 10 ++++++++
.../org/apache/cayenne/query/SQLSelectIT.java | 21 +++++++++++++++++
.../org/apache/cayenne/query/SelectQueryIT.java | 24 ++++++++++++++++++++
11 files changed, 145 insertions(+), 41 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44fdc845/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java b/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java
index dd61318..45881c9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java
@@ -18,13 +18,6 @@
****************************************************************/
package org.apache.cayenne;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
import org.apache.cayenne.cache.NestedQueryCache;
import org.apache.cayenne.cache.QueryCache;
import org.apache.cayenne.configuration.CayenneRuntime;
@@ -50,6 +43,13 @@ import org.apache.cayenne.reflect.ToManyProperty;
import org.apache.cayenne.reflect.ToOneProperty;
import org.apache.cayenne.util.ObjectContextGraphAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
/**
* A common base superclass for Cayenne ObjectContext implementors.
*
@@ -327,6 +327,16 @@ public abstract class BaseContext implements ObjectContext {
* @since 4.0
*/
@Override
+ public <T> T selectFirst(Select<T> query) {
+ List<T> objects = select(query);
+
+ return (objects == null || objects.isEmpty()) ? null : objects.get(0);
+ }
+
+ /**
+ * @since 4.0
+ */
+ @Override
public <T> void iterate(Select<T> query, ResultIteratorCallback<T> callback) {
ResultIterator<T> it = iterator(query);
try {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44fdc845/cayenne-server/src/main/java/org/apache/cayenne/ObjectContext.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/ObjectContext.java b/cayenne-server/src/main/java/org/apache/cayenne/ObjectContext.java
index 5efb19a..8f0c1dd 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/ObjectContext.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/ObjectContext.java
@@ -194,6 +194,25 @@ public interface ObjectContext extends DataChannel, Serializable {
<T> T selectOne(Select<T> query);
/**
+ * Selects a single object using provided query. The query itself can
+ * match any number of objects, but will return only the first one. It
+ * returns null if no objects were matched.
+ * <p>
+ * If it matched more than one object, the first object from the list is
+ * returned. This makes 'selectFirst' different from
+ * {@link #selectOne(Select)}, which would throw in this situation.
+ * 'selectFirst' is useful e.g. when the query is ordered and we only want
+ * to see the first object (e.g. "most recent news article"), etc.
+ * <p>
+ * Selecting the first object via "Select.selectFirst(ObjectContext)"
+ * is more comprehensible than selecting via "ObjectContext.selectFirst(Select)",
+ * because implementations of "Select" set fetch size limit to one.
+ *
+ * @since 4.0
+ */
+ <T> T selectFirst(Select<T> query);
+
+ /**
* Creates a ResultIterator based on the provided query and passes it to a
* callback for processing. The caller does not need to worry about closing
* the iterator. This method takes care of it.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44fdc845/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 1c9f53b..5d7172d 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
@@ -665,6 +665,11 @@ public class ObjectSelect<T> extends IndirectQuery implements Select<T> {
}
@Override
+ public T selectFirst(ObjectContext context) {
+ return context.selectFirst(limit(1));
+ }
+
+ @Override
public <T> void iterate(ObjectContext context, ResultIteratorCallback<T> callback) {
context.iterate((Select<T>) this, callback);
}
@@ -674,21 +679,4 @@ public class ObjectSelect<T> extends IndirectQuery implements Select<T> {
return context.iterator(this);
}
- /**
- * Selects a single object using provided context. The query itself can
- * match any number of objects, but will return only the first one. It
- * returns null if no objects were matched.
- * <p>
- * If it matched more than one object, the first object from the list is
- * returned. This makes 'selectFirst' different from
- * {@link #selectOne(ObjectContext)}, which would throw in this situation.
- * 'selectFirst' is useful e.g. when the query is ordered and we only want
- * to see the first object (e.g. "most recent news article"), etc.
- * <p>
- * This method is equivalent to calling "limit(1).selectOne(context)".
- */
- public T selectFirst(ObjectContext context) {
- return limit(1).selectOne(context);
- }
-
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44fdc845/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
index 2a51081..e93fc50 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
@@ -125,6 +125,11 @@ public class SQLSelect<T> extends IndirectQuery implements Select<T> {
}
@Override
+ public T selectFirst(ObjectContext context) {
+ return context.selectFirst(limit(1));
+ }
+
+ @Override
public <T> void iterate(ObjectContext context, ResultIteratorCallback<T> callback) {
context.iterate((Select<T>) this, callback);
}
@@ -134,23 +139,6 @@ public class SQLSelect<T> extends IndirectQuery implements Select<T> {
return context.iterator(this);
}
- /**
- * Selects a single object using provided context. The query itself can
- * match any number of objects, but will return only the first one. It
- * returns null if no objects were matched.
- * <p>
- * If it matched more than one object, the first object from the list is
- * returned. This makes 'selectFirst' different from
- * {@link #selectOne(ObjectContext)}, which would throw in this situation.
- * 'selectFirst' is useful e.g. when the query is ordered and we only want
- * to see the first object (e.g. "most recent news article"), etc.
- * <p>
- * This method is equivalent to calling "limit(1).selectOne(context)".
- */
- public T selectFirst(ObjectContext context) {
- return limit(1).selectOne(context);
- }
-
public boolean isFetchingDataRows() {
return persistentType == null;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44fdc845/cayenne-server/src/main/java/org/apache/cayenne/query/Select.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/Select.java b/cayenne-server/src/main/java/org/apache/cayenne/query/Select.java
index 4cfe9f3..f744d5c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/Select.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/Select.java
@@ -35,6 +35,7 @@ public interface Select<T> extends Query {
* Selects objects using provided context.
* <p>
* Essentially the inversion of "ObjectContext.select(Select)".
+ *
* @since 4.0
*/
<T> List<T> select(ObjectContext context);
@@ -46,15 +47,37 @@ public interface Select<T> extends Query {
* thrown.
* <p>
* Essentially the inversion of "ObjectContext.selectOne(Select)".
+ *
+ * @since 4.0
*/
<T> T selectOne(ObjectContext context);
/**
+ * Selects a single object using provided context. The query itself can
+ * match any number of objects, but will return only the first one. It
+ * returns null if no objects were matched.
+ * <p>
+ * If it matched more than one object, the first object from the list is
+ * returned. This makes 'selectFirst' different from
+ * {@link #selectOne(ObjectContext)}, which would throw in this situation.
+ * 'selectFirst' is useful e.g. when the query is ordered and we only want
+ * to see the first object (e.g. "most recent news article"), etc.
+ * <p>
+ * Selecting the first object via "Select.selectFirst(ObjectContext)"
+ * is more comprehensible than selecting via "ObjectContext.selectFirst(Select)",
+ * because implementations of "Select" set fetch size limit to one.
+ *
+ * @since 4.0
+ */
+ <T> T selectFirst(ObjectContext context);
+
+ /**
* Creates a ResultIterator based on the provided context and passes it to a
* callback for processing. The caller does not need to worry about closing
* the iterator. This method takes care of it.
* <p>
* Essentially the inversion of "ObjectContext.iterate(Select, ResultIteratorCallback)".
+ *
* @since 4.0
*/
<T> void iterate(ObjectContext context, ResultIteratorCallback<T> callback);
@@ -68,6 +91,7 @@ public interface Select<T> extends Query {
* Or use {@link #iterate(ObjectContext, ResultIteratorCallback)} as an alternative.
* <p>
* Essentially the inversion of "ObjectContext.iterator(Select)".
+ *
* @since 4.0
*/
<T> ResultIterator<T> iterator(ObjectContext context);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44fdc845/cayenne-server/src/main/java/org/apache/cayenne/query/SelectById.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectById.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectById.java
index 4c3187f..50c0750 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectById.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectById.java
@@ -143,6 +143,15 @@ public class SelectById<T> extends IndirectQuery implements Select<T> {
return context.selectOne(this);
}
+ /**
+ * Since we are selecting by ID, we don't need to limit fetch size.
+ * Multiple matched objects likely indicate a database referential integrity problem.
+ */
+ @Override
+ public T selectFirst(ObjectContext context) {
+ return selectFirst(context);
+ }
+
@Override
public <T> void iterate(ObjectContext context, ResultIteratorCallback<T> callback) {
context.iterate((Select<T>) this, callback);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44fdc845/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
index fd446b8..f116af7 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
@@ -318,6 +318,12 @@ public class SelectQuery<T> extends AbstractQuery implements ParameterizedQuery,
}
@Override
+ public T selectFirst(ObjectContext context) {
+ setFetchLimit(1);
+ return context.selectFirst(this);
+ }
+
+ @Override
public <T> void iterate(ObjectContext context, ResultIteratorCallback<T> callback) {
context.iterate((Select<T>) this, callback);
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44fdc845/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
index 451885c..a1cd059 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
@@ -355,6 +355,11 @@ class IncrementalSelectQuery<T> extends SelectQuery<T> {
}
@Override
+ public T selectFirst(ObjectContext context) {
+ return query.selectFirst(context);
+ }
+
+ @Override
public <T> void iterate(ObjectContext context, ResultIteratorCallback<T> callback) {
query.iterate(context, callback);
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44fdc845/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java
index 8c018aa..8cd551d 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java
@@ -154,6 +154,16 @@ public class ObjectSelect_RunIT extends ServerCase {
assertEquals("artist13", a.getArtistName());
}
+ @Test
+ public void test_SelectFirstByContext() throws Exception {
+ createArtistsDataSet();
+
+ ObjectSelect<Artist> q = ObjectSelect.query(Artist.class).where(Artist.ARTIST_NAME.eq("artist13"));
+ Artist a = context.selectFirst(q);
+ assertNotNull(a);
+ assertEquals("artist13", a.getArtistName());
+ }
+
@Test
public void test_SelectFirst_NoMatch() throws Exception {
Artist a = ObjectSelect.query(Artist.class).where(Artist.ARTIST_NAME.eq("artist13")).selectFirst(context);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44fdc845/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
index 8a5f209..0061a84 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
@@ -202,6 +202,27 @@ public class SQLSelectIT extends ServerCase {
}
@Test
+ public void test_SelectFirst() throws Exception {
+ createPaintingsDataSet();
+
+ Painting p = SQLSelect.query(Painting.class, "SELECT * FROM PAINTING ORDER BY PAINTING_TITLE").selectFirst(context);
+
+ assertNotNull(p);
+ assertEquals("painting1", p.getPaintingTitle());
+ }
+
+ @Test
+ public void test_SelectFirstByContext() throws Exception {
+ createPaintingsDataSet();
+
+ SQLSelect<Painting> q = SQLSelect.query(Painting.class, "SELECT * FROM PAINTING ORDER BY PAINTING_TITLE");
+ Painting p = context.selectFirst(q);
+
+ assertNotNull(p);
+ assertEquals("painting1", p.getPaintingTitle());
+ }
+
+ @Test
public void test_Iterate() throws Exception {
createPaintingsDataSet();
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44fdc845/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java
index cf532f4..785e1a7 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java
@@ -512,6 +512,30 @@ public class SelectQueryIT extends ServerCase {
}
@Test
+ public void testSelectFirst() throws Exception {
+ createArtistsDataSet();
+
+ SelectQuery query = new SelectQuery(Artist.class);
+ query.addOrdering(new Ordering(Artist.ARTIST_NAME.getName()));
+ Artist artist = (Artist) query.selectFirst(context);
+
+ assertNotNull(artist);
+ assertEquals("artist1", artist.getArtistName());
+ }
+
+ @Test
+ public void testSelectFirstByContext() throws Exception {
+ createArtistsDataSet();
+
+ SelectQuery query = new SelectQuery(Artist.class);
+ query.addOrdering(new Ordering(Artist.ARTIST_NAME.getName()));
+ Artist artist = (Artist) context.selectFirst(query);
+
+ assertNotNull(artist);
+ assertEquals("artist1", artist.getArtistName());
+ }
+
+ @Test
public void testIterate() throws Exception {
createArtistsDataSet();