Repository: cayenne Updated Branches: refs/heads/master 16e5513cd -> 047a29477
CAY-1959 Chainable API for SelectQuery * 'selectFirst' method Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/047a2947 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/047a2947 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/047a2947 Branch: refs/heads/master Commit: 047a29477202b145b9f14e0bd7aea312500a6e10 Parents: 16e5513 Author: aadamchik <[email protected]> Authored: Sat Nov 22 14:09:26 2014 +0300 Committer: aadamchik <[email protected]> Committed: Fri Nov 28 16:58:38 2014 +0300 ---------------------------------------------------------------------- .../org/apache/cayenne/query/ObjectSelect.java | 25 +++++++- .../org/apache/cayenne/query/SQLSelect.java | 25 +++++++- .../org/apache/cayenne/query/SelectById.java | 9 ++- .../cayenne/query/ObjectSelect_RunIT.java | 61 +++++++++++++++++--- 4 files changed, 107 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/047a2947/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 b6395dc..022bcf6 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 @@ -661,11 +661,32 @@ public class ObjectSelect<T> extends IndirectQuery implements Select<T> { } /** - * Selects a single object using provided context. Essentially the inversion - * of "ObjectContext.selectOne(Select)". + * Selects a single object using provided context. The query is expected to + * match zero or one object. It returns null if no objects were matched. If + * query matched more than one object, {@link CayenneRuntimeException} is + * thrown. + * <p> + * Essentially the inversion of "ObjectContext.selectOne(Select)". */ public T selectOne(ObjectContext context) { return context.selectOne(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/047a2947/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 b4504f4..ebd5d58 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 @@ -121,13 +121,34 @@ public class SQLSelect<T> extends IndirectQuery implements Select<T> { } /** - * Selects a single object using provided context. Essentially the inversion - * of "ObjectContext.selectOne(Select)". + * Selects a single object using provided context. The query is expected to + * match zero or one object. It returns null if no objects were matched. If + * query matched more than one object, {@link CayenneRuntimeException} is + * thrown. + * <p> + * Essentially the inversion of "ObjectContext.selectOne(Select)". */ public T selectOne(ObjectContext context) { return context.selectOne(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/047a2947/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 bec8c75..00ee205 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 @@ -125,8 +125,13 @@ public class SelectById<T> extends IndirectQuery implements Select<T> { } /** - * Selects a single object using provided context. Essentially the inversion - * of "ObjectContext.selectOne(Select)". + * Selects a single object using provided context. The query is expected to + * match zero or one object. It returns null if no objects were matched. If + * query matched more than one object, {@link CayenneRuntimeException} is + * thrown. Since we are selecting by ID, multiple matched objects likely + * indicate a database referential integrity problem. + * <p> + * Essentially the inversion of "ObjectContext.selectOne(Select)". */ public T selectOne(ObjectContext context) { return context.selectOne(this); http://git-wip-us.apache.org/repos/asf/cayenne/blob/047a2947/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 194b94b..17e128b 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 @@ -18,6 +18,15 @@ ****************************************************************/ package org.apache.cayenne.query; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; + +import java.util.List; + +import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.DataRow; import org.apache.cayenne.access.DataContext; import org.apache.cayenne.di.Inject; @@ -29,13 +38,6 @@ import org.apache.cayenne.unit.di.server.ServerCase; import org.apache.cayenne.unit.di.server.UseServerRuntime; import org.junit.Test; -import java.util.List; - -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; - @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT) public class ObjectSelect_RunIT extends ServerCase { @@ -83,4 +85,49 @@ public class ObjectSelect_RunIT extends ServerCase { assertNotNull(a); assertEquals("artist14", a.get("ARTIST_NAME")); } + + @Test + public void test_SelectOne() throws Exception { + createArtistsDataSet(); + + Artist a = ObjectSelect.query(Artist.class).where(Artist.ARTIST_NAME.eq("artist13")).selectOne(context); + assertNotNull(a); + assertEquals("artist13", a.getArtistName()); + } + + @Test + public void test_SelectOne_NoMatch() throws Exception { + Artist a = ObjectSelect.query(Artist.class).where(Artist.ARTIST_NAME.eq("artist13")).selectOne(context); + assertNull(a); + } + + @Test(expected = CayenneRuntimeException.class) + public void test_SelectOne_MoreThanOneMatch() throws Exception { + createArtistsDataSet(); + ObjectSelect.query(Artist.class).where(Artist.ARTIST_NAME.like("artist%")).selectOne(context); + } + + @Test + public void test_SelectFirst() throws Exception { + createArtistsDataSet(); + + Artist a = ObjectSelect.query(Artist.class).where(Artist.ARTIST_NAME.eq("artist13")).selectFirst(context); + 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); + assertNull(a); + } + + @Test + public void test_SelectFirst_MoreThanOneMatch() throws Exception { + createArtistsDataSet(); + + Artist a = ObjectSelect.query(Artist.class).where(Artist.ARTIST_NAME.like("artist%")).orderBy("db:ARTIST_ID").selectFirst(context); + assertNotNull(a); + assertEquals("artist1", a.getArtistName()); + } }
