cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From abulat...@apache.org
Subject [cayenne] branch master updated: CAY-2378 Switch usage of SelectQuery to ObjectSelect internally
Date Mon, 12 Aug 2019 13:45:59 GMT
This is an automated email from the ASF dual-hosted git repository.

abulatski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git


The following commit(s) were added to refs/heads/master by this push:
     new 55cfd6e  CAY-2378 Switch usage of SelectQuery to ObjectSelect internally
55cfd6e is described below

commit 55cfd6e9e2bedba54ca60db9c56aa679bd3b1674
Author: Arseni Bulatski <ancarseni@gmail.com>
AuthorDate: Mon Aug 12 16:45:41 2019 +0300

    CAY-2378 Switch usage of SelectQuery to ObjectSelect internally
---
 .../cayenne/access/DataContextCharTypeIT.java      |  35 ++--
 .../cayenne/access/DataContextDelegateIT.java      |  18 +-
 .../access/DataContextEJBQLConditionsIT.java       |  28 ++-
 .../DataContextExtendedTypeOperationsIT.java       |  15 +-
 .../cayenne/access/DataContextOrderingIT.java      |  29 ++-
 .../access/DataContextPaginatedQueryIT.java        |  22 +-
 .../access/DataContextPrefetchExtras1IT.java       |  16 +-
 .../access/DataContextPrefetchExtrasIT.java        |  39 ++--
 .../cayenne/access/DataContextPrefetchIT.java      | 194 +++++++++---------
 .../DataContextPrefetchQualifierOverlapIT.java     |  40 ++--
 .../access/DataContextProcedureQueryIT.java        |  31 +--
 .../cayenne/access/DataContextRefreshQueryIT.java  |  87 ++++----
 .../cayenne/access/DataContextRefreshingIT.java    |  90 ++++-----
 .../cayenne/access/DataContextRollbackIT.java      |  39 ++--
 .../access/DataContextSharedCacheEmpiricIT.java    |  42 ++--
 .../cayenne/access/DataContextSharedCacheIT.java   |  25 +--
 .../cayenne/access/DataDomainCallbacksIT.java      |  24 +--
 .../apache/cayenne/access/DataDomainFiltersIT.java |  12 +-
 .../cayenne/access/DataDomainQueryActionIT.java    |  21 +-
 .../org/apache/cayenne/access/DataRowUtilsIT.java  |  27 +--
 .../org/apache/cayenne/access/DateTimeTypesIT.java |  32 +--
 .../java/org/apache/cayenne/access/EnumIT.java     |   1 +
 .../apache/cayenne/access/FlattenedPrefetchIT.java |  51 +++--
 .../apache/cayenne/access/IdentityColumnsIT.java   |  14 +-
 .../cayenne/access/IncrementalFaultListIT.java     |  10 +-
 .../org/apache/cayenne/access/MiscTypesIT.java     |  48 +++--
 .../access/NestedDataContextLocalCacheIT.java      |  12 +-
 .../cayenne/access/NestedDataContextWriteIT.java   |  62 +++---
 .../org/apache/cayenne/access/NumericTypesIT.java  |  72 +++----
 .../apache/cayenne/access/OptimisticLockingIT.java | 109 +++++-----
 .../cayenne/access/ReturnTypesMappingIT.java       | 224 ++++++++++++---------
 .../access/SimpleIdIncrementalFaultListIT.java     |  49 +++--
 .../SimpleIdIncrementalFaultListPrefetchIT.java    |  75 +++----
 .../cayenne/access/SingleTableInheritance1IT.java  |   8 +-
 .../cayenne/access/SingleTableInheritanceIT.java   | 146 ++++++--------
 .../java/org/apache/cayenne/access/UUIDIT.java     |   9 +-
 .../cayenne/access/VerticalInheritanceIT.java      |  38 ++--
 37 files changed, 886 insertions(+), 908 deletions(-)

diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextCharTypeIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextCharTypeIT.java
index 61a787a..2fde968 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextCharTypeIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextCharTypeIT.java
@@ -18,10 +18,11 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.util.List;
+
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.testdo.return_types.ReturnTypesMap1;
 import org.apache.cayenne.unit.UnitDbAdapter;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
@@ -29,19 +30,17 @@ 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.junit.Assert.assertTrue;
 
 @UseServerRuntime(CayenneProjects.RETURN_TYPES_PROJECT)
 public class DataContextCharTypeIT extends ServerCase {
-    
+
     @Inject
     protected ObjectContext context;
-    
+
     @Inject
     private UnitDbAdapter unitDbAdapter;
-    
+
     @Test
     public void testCharTrimming() {
         if (unitDbAdapter.supportsLobs()) {
@@ -51,20 +50,20 @@ public class DataContextCharTypeIT extends ServerCase {
             map2.setCharColumn("  text");
             ReturnTypesMap1 map3 = context.newObject(ReturnTypesMap1.class);
             map3.setCharColumn("text     ");
-            
+
             context.commitChanges();
-            
-            Expression qual = ReturnTypesMap1.CHAR_COLUMN.eq("  text");
-            SelectQuery query = new SelectQuery(ReturnTypesMap1.class, qual);
-            List<ReturnTypesMap1> result =  context.performQuery(query);
-            
+
+            List<ReturnTypesMap1> result =  ObjectSelect.query(ReturnTypesMap1.class)
+                    .where(ReturnTypesMap1.CHAR_COLUMN.eq("  text"))
+                    .select(context);
+
             assertTrue("CHAR type trimming is not valid.", result.get(0).getCharColumn().startsWith("  text"));
             assertTrue("CHAR type trimming is not valid.", result.get(1).getCharColumn().startsWith("  text"));
-            
-            qual = ReturnTypesMap1.CHAR_COLUMN.eq("text");
-            query = new SelectQuery(ReturnTypesMap1.class, qual);
-            result =  context.performQuery(query);
-            
+
+            result =  ObjectSelect.query(ReturnTypesMap1.class)
+                    .where(ReturnTypesMap1.CHAR_COLUMN.eq("text"))
+                    .select(context);
+
             assertTrue("CHAR type trimming is not valid.", result.get(0).getCharColumn().startsWith("text"));
         }
     }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextDelegateIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextDelegateIT.java
index 217ec10..c9b604b 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextDelegateIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextDelegateIT.java
@@ -19,10 +19,13 @@
 
 package org.apache.cayenne.access;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.query.MockQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.Query;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.testdo.testmap.Gallery;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
@@ -31,9 +34,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -123,9 +123,9 @@ public class DataContextDelegateIT extends ServerCase {
         };
         context.setDelegate(delegate);
 
-        // test that delegate is consulted before select
-        SelectQuery query = new SelectQuery(Gallery.class);
-        List<?> results = context.performQuery(query);
+        // test that delegate is consulted before select;
+        ObjectSelect<Gallery> query = ObjectSelect.query(Gallery.class);
+        List<Gallery> results = query.select(context);
 
         assertTrue("Delegate is not notified of a query being run.", queriesPerformed
                 .contains(query));
@@ -147,8 +147,8 @@ public class DataContextDelegateIT extends ServerCase {
         };
 
         context.setDelegate(delegate);
-        SelectQuery query = new SelectQuery(Gallery.class);
-        List<?> results = context.performQuery(query);
+        ObjectSelect<Gallery> query = ObjectSelect.query(Gallery.class);
+        List<Gallery> results = query.select(context);
 
         assertTrue("Delegate is not notified of a query being run.", queriesPerformed
                 .contains(query));
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLConditionsIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLConditionsIT.java
index 0a424d1..bb58150 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLConditionsIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextEJBQLConditionsIT.java
@@ -18,12 +18,20 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.math.BigDecimal;
+import java.sql.Types;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
 import org.apache.cayenne.Cayenne;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.query.EJBQLQuery;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.testmap.Artist;
@@ -34,19 +42,7 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.math.BigDecimal;
-import java.sql.Types;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
 public class DataContextEJBQLConditionsIT extends ServerCase {
@@ -115,8 +111,8 @@ public class DataContextEJBQLConditionsIT extends ServerCase {
     public void testDateParameter() throws Exception {
         createCollectionDataSet();
 
-        SelectQuery q = new SelectQuery(Artist.class);
-        List<Artist> allArtists = context.performQuery(q);
+        ObjectSelect<Artist> q = ObjectSelect.query(Artist.class);
+        List<Artist> allArtists = q.select(context);
 
         Date dob = new Date();
         allArtists.get(0).setDateOfBirth(dob);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextExtendedTypeOperationsIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextExtendedTypeOperationsIT.java
index 2111178..4d8127f 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextExtendedTypeOperationsIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextExtendedTypeOperationsIT.java
@@ -18,12 +18,13 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.util.Arrays;
+
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.query.CapsStrategy;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.SQLTemplate;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.testdo.extended_type.ExtendedTypeEntity;
 import org.apache.cayenne.testdo.extended_type.StringET1;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
@@ -31,8 +32,6 @@ import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Test;
 
-import java.util.Arrays;
-
 import static org.junit.Assert.assertEquals;
 
 @UseServerRuntime(CayenneProjects.EXTENDED_TYPE_PROJECT)
@@ -68,8 +67,8 @@ public class DataContextExtendedTypeOperationsIT extends ServerCase {
 
         e1.getObjectContext().commitChanges();
 
-        Expression in = ExtendedTypeEntity.NAME.in(new StringET1("X"), new StringET1("Y"));
-        SelectQuery query = new SelectQuery(ExtendedTypeEntity.class, in);
+        ObjectSelect<ExtendedTypeEntity> query = ObjectSelect.query(ExtendedTypeEntity.class)
+                .where(ExtendedTypeEntity.NAME.in(new StringET1("X"), new StringET1("Y")));
         assertEquals(2, e1.getObjectContext().performQuery(query).size());
     }
 
@@ -86,8 +85,8 @@ public class DataContextExtendedTypeOperationsIT extends ServerCase {
 
         e1.getObjectContext().commitChanges();
 
-        Expression in = ExtendedTypeEntity.NAME.in(Arrays.asList(new StringET1("X"), new StringET1("Y")));
-        SelectQuery query = new SelectQuery(ExtendedTypeEntity.class, in);
+        ObjectSelect<ExtendedTypeEntity> query = ObjectSelect.query(ExtendedTypeEntity.class)
+                .where(ExtendedTypeEntity.NAME.in(Arrays.asList(new StringET1("X"), new StringET1("Y"))));
         assertEquals(2, e1.getObjectContext().performQuery(query).size());
     }
 }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextOrderingIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextOrderingIT.java
index 351bbdd..6a373af 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextOrderingIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextOrderingIT.java
@@ -18,8 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.List;
+
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.testdo.testmap.Painting;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
@@ -27,10 +31,6 @@ import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Test;
 
-import java.math.BigDecimal;
-import java.util.Calendar;
-import java.util.List;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
 
@@ -61,9 +61,8 @@ public class DataContextOrderingIT extends ServerCase {
 
         context.commitChanges();
 
-        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
-        query.addOrdering(Artist.ARTIST_NAME.desc());
-        query.addOrdering(Artist.DATE_OF_BIRTH.desc());
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                .orderBy(Artist.ARTIST_NAME.desc(), Artist.DATE_OF_BIRTH.desc());
 
         List<Artist> list = query.select(context);
         assertEquals(3, list.size());
@@ -103,12 +102,10 @@ public class DataContextOrderingIT extends ServerCase {
 
         context.commitChanges();
 
-        SelectQuery<Artist> query1 = new SelectQuery<>(Artist.class);
-
-        // per CAY-1074, adding a to-many join to expression messes up the ordering
-        query1.andQualifier(Artist.PAINTING_ARRAY.ne((List<Painting>) null));
-        query1.addOrdering(Artist.ARTIST_NAME.desc());
-        query1.addOrdering(Artist.DATE_OF_BIRTH.desc());
+        ObjectSelect<Artist> query1 = ObjectSelect.query(Artist.class)
+                // per CAY-1074, adding a to-many join to expression messes up the ordering
+                .and(Artist.PAINTING_ARRAY.ne((List<Painting>) null))
+                .orderBy(Artist.ARTIST_NAME.desc(), (Artist.DATE_OF_BIRTH.desc()));
 
         List<Artist> list1 = query1.select(context);
         assertEquals(2, list1.size());
@@ -134,8 +131,8 @@ public class DataContextOrderingIT extends ServerCase {
 
         context.commitChanges();
 
-        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
-        query.addOrdering(Artist.ARTIST_NAME.substring(2, 1).desc());
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                .orderBy(Artist.ARTIST_NAME.substring(2, 1).desc());
 
         List<Artist> list = query.select(context);
         assertEquals(3, list.size());
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPaginatedQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPaginatedQueryIT.java
index b64162d..1f20408 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPaginatedQueryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPaginatedQueryIT.java
@@ -18,9 +18,11 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.util.List;
+
 import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.QueryCacheStrategy;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.testmap.Artist;
@@ -30,8 +32,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.List;
-
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
 
@@ -70,25 +70,25 @@ public class DataContextPaginatedQueryIT extends ServerCase {
 
         createArtistsDataSet();
 
-        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
-        query.addOrdering(Artist.ARTIST_NAME.asc());
-        query.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-        query.setPageSize(5);
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                .orderBy(Artist.ARTIST_NAME.asc())
+                .cacheStrategy(QueryCacheStrategy.LOCAL_CACHE)
+                .pageSize(5);
 
-        List<?> results1 = context.performQuery(query);
+        List<Artist> results1 = query.select(context);
         assertNotNull(results1);
 
-        List<?> results2 = context.performQuery(query);
+        List<Artist> results2 = query.select(context);
         assertNotNull(results2);
         assertSame(results1, results2);
 
         results1.get(1);
-        List<?> results3 = context.performQuery(query);
+        List<Artist> results3 = query.select(context);
         assertNotNull(results3);
         assertSame(results1, results3);
 
         results1.get(7);
-        List<?> results4 = context.performQuery(query);
+        List<Artist> results4 = query.select(context);
         assertNotNull(results4);
         assertSame(results1, results4);
     }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchExtras1IT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchExtras1IT.java
index 8a8403d..a8c040b 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchExtras1IT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchExtras1IT.java
@@ -18,10 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.util.List;
+
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.PersistenceState;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.testmap.Painting;
@@ -31,10 +33,8 @@ 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.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
 
 /**
  * A test case for CAY-788.
@@ -66,11 +66,11 @@ public class DataContextPrefetchExtras1IT extends ServerCase {
     public void testPrefetchToOne() throws Exception {
         createDataSet();
 
-        SelectQuery query = new SelectQuery(Painting.class);
-        query.addPrefetch(Painting.TO_PAINTING_INFO.disjoint());
+        ObjectSelect<Painting> query = ObjectSelect.query(Painting.class)
+                .prefetch(Painting.TO_PAINTING_INFO.disjoint());
 
-        List<Painting> objects = context.performQuery(query);
-        assertTrue(!objects.isEmpty());
+        List<Painting> objects = query.select(context);
+        assertFalse(objects.isEmpty());
         for (Painting p : objects) {
             PaintingInfo pi = p.getToPaintingInfo();
             assertEquals(PersistenceState.COMMITTED, p.getPersistenceState());
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchExtrasIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchExtrasIT.java
index ff7d6e5..0fd388f 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchExtrasIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchExtrasIT.java
@@ -19,15 +19,16 @@
 
 package org.apache.cayenne.access;
 
+import java.util.List;
+
 import org.apache.cayenne.BaseDataObject;
 import org.apache.cayenne.DataObject;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.PersistenceState;
 import org.apache.cayenne.ValueHolder;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.PrefetchTreeNode;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.compound.CharFkTestEntity;
@@ -40,8 +41,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.List;
-
 import static org.junit.Assert.*;
 
 /**
@@ -101,14 +100,14 @@ public class DataContextPrefetchExtrasIT extends ServerCase {
     public void testPrefetchToManyOnCharKey() throws Exception {
         createPrefetchToManyOnCharKeyDataSet();
 
-        SelectQuery q = new SelectQuery(CharPkTestEntity.class);
-        q.addPrefetch("charFKs");
-        q.addOrdering(CharPkTestEntity.OTHER_COL.asc());
+        ObjectSelect<CharPkTestEntity> q = ObjectSelect.query(CharPkTestEntity.class)
+                .prefetch("charFKs", PrefetchTreeNode.UNDEFINED_SEMANTICS)
+                .orderBy(CharPkTestEntity.OTHER_COL.asc());
 
-        List<?> pks = context.performQuery(q);
+        List<CharPkTestEntity> pks = q.select(context);
         assertEquals(2, pks.size());
 
-        CharPkTestEntity pk1 = (CharPkTestEntity) pks.get(0);
+        CharPkTestEntity pk1 = pks.get(0);
         assertEquals("n1", pk1.getOtherCol());
         List<?> toMany = (List<?>) pk1.readPropertyDirectly("charFKs");
         assertNotNull(toMany);
@@ -127,13 +126,13 @@ public class DataContextPrefetchExtrasIT extends ServerCase {
     public void testPrefetch10() throws Exception {
         createCompoundDataSet();
 
-        Expression e = ExpressionFactory.matchExp("name", "CFK2");
-        SelectQuery q = new SelectQuery(CompoundFkTestEntity.class, e);
-        q.addPrefetch("toCompoundPk");
+        ObjectSelect<CompoundFkTestEntity> q = ObjectSelect.query(CompoundFkTestEntity.class)
+                .where(CompoundFkTestEntity.NAME.eq("CFK2"))
+                .prefetch("toCompoundPk", PrefetchTreeNode.UNDEFINED_SEMANTICS);
 
-        List<?> objects = context.performQuery(q);
+        List<CompoundFkTestEntity> objects = q.select(context);
         assertEquals(1, objects.size());
-        BaseDataObject fk1 = (BaseDataObject) objects.get(0);
+        BaseDataObject fk1 = objects.get(0);
 
         Object toOnePrefetch = fk1.readNestedProperty("toCompoundPk");
         assertNotNull(toOnePrefetch);
@@ -153,13 +152,13 @@ public class DataContextPrefetchExtrasIT extends ServerCase {
     public void testPrefetch11() throws Exception {
         createCompoundDataSet();
 
-        Expression e = ExpressionFactory.matchExp("name", "CPK2");
-        SelectQuery q = new SelectQuery(CompoundPkTestEntity.class, e);
-        q.addPrefetch("compoundFkArray");
+        ObjectSelect<CompoundPkTestEntity> q = ObjectSelect.query(CompoundPkTestEntity.class)
+                .where(CompoundPkTestEntity.NAME.eq("CPK2"))
+                .prefetch("compoundFkArray", PrefetchTreeNode.UNDEFINED_SEMANTICS);
 
-        List<?> pks = context.performQuery(q);
+        List<CompoundPkTestEntity> pks = q.select(context);
         assertEquals(1, pks.size());
-        BaseDataObject pk1 = (BaseDataObject) pks.get(0);
+        BaseDataObject pk1 = pks.get(0);
 
         List<?> toMany = (List<?>) pk1.readPropertyDirectly("compoundFkArray");
         assertNotNull(toMany);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchIT.java
index 9dbb3bb..1b462f2 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchIT.java
@@ -19,6 +19,14 @@
 
 package org.apache.cayenne.access;
 
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.cayenne.Cayenne;
 import org.apache.cayenne.Fault;
 import org.apache.cayenne.PersistenceState;
@@ -30,8 +38,8 @@ import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
 import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.PrefetchTreeNode;
 import org.apache.cayenne.query.QueryCacheStrategy;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.testmap.ArtGroup;
@@ -47,14 +55,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.sql.Types;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import static org.junit.Assert.*;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
@@ -154,10 +154,10 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetchToMany_ViaPath() throws Exception {
 		createTwoArtistsAndTwoPaintingsDataSet();
 
-		SelectQuery<Artist> q = new SelectQuery<>(Artist.class);
-		q.addPrefetch("paintingArray");
+		ObjectSelect<Artist> q = ObjectSelect.query(Artist.class)
+				.prefetch("paintingArray", PrefetchTreeNode.UNDEFINED_SEMANTICS);
 
-		final List<Artist> artists = context.select(q);
+		final List<Artist> artists = q.select(context);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
 
@@ -184,10 +184,11 @@ public class DataContextPrefetchIT extends ServerCase {
 		params.put("name1", "artist2");
 		params.put("name2", "artist3");
 		Expression e = ExpressionFactory.exp("artistName = $name1 or artistName = $name2");
-		SelectQuery<Artist> q = new SelectQuery<>("Artist", e.params(params));
-		q.addPrefetch(Artist.PAINTING_ARRAY.disjoint());
+		ObjectSelect<Artist> q = ObjectSelect.query(Artist.class)
+				.where(e.params(params))
+				.prefetch(Artist.PAINTING_ARRAY.disjoint());
 
-		final List<Artist> artists = context.select(q);
+		final List<Artist> artists = q.select(context);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
 
@@ -217,10 +218,10 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetchToManyNoQualifier() throws Exception {
 		createTwoArtistsAndTwoPaintingsDataSet();
 
-		SelectQuery<Artist> q = new SelectQuery<>(Artist.class);
-		q.addPrefetch(Artist.PAINTING_ARRAY.disjoint());
+		ObjectSelect<Artist> q = ObjectSelect.query(Artist.class)
+				.prefetch(Artist.PAINTING_ARRAY.disjoint());
 
-		final List<Artist> artists = context.select(q);
+		final List<Artist> artists = q.select(context);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
 
@@ -248,11 +249,11 @@ public class DataContextPrefetchIT extends ServerCase {
 
 		createTwoArtistsWithExhibitsDataSet();
 
-		SelectQuery<Artist> q = new SelectQuery<>(Artist.class);
-		q.addPrefetch(Artist.ARTIST_EXHIBIT_ARRAY.disjoint());
-		q.addOrdering(Artist.ARTIST_NAME.asc());
+		ObjectSelect<Artist> q = ObjectSelect.query(Artist.class)
+				.prefetch(Artist.ARTIST_EXHIBIT_ARRAY.disjoint())
+				.orderBy(Artist.ARTIST_NAME.asc());
 
-		final List<Artist> artists = context.select(q);
+		final List<Artist> artists = q.select(context);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
 			assertEquals(2, artists.size());
@@ -285,11 +286,11 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetchToMany_OnJoinTableJoinedPrefetch() throws Exception {
 		createTwoArtistsWithExhibitsDataSet();
 
-		SelectQuery<Artist> q = new SelectQuery<>(Artist.class);
-		q.addPrefetch(Artist.ARTIST_EXHIBIT_ARRAY.joint());
-		q.addOrdering(Artist.ARTIST_NAME.asc());
+		ObjectSelect<Artist> q = ObjectSelect.query(Artist.class)
+				.prefetch(Artist.ARTIST_EXHIBIT_ARRAY.joint())
+				.orderBy(Artist.ARTIST_NAME.asc());
 
-		final List<Artist> artists = context.select(q);
+		final List<Artist> artists = q.select(context);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
 
@@ -332,9 +333,10 @@ public class DataContextPrefetchIT extends ServerCase {
 		paintingEntity.removeRelationship("toArtist");
 
 		try {
-			SelectQuery<Artist> q = new SelectQuery<>(Artist.class);
-			q.addPrefetch(Artist.PAINTING_ARRAY.disjoint());
-			final List<Artist> result = context.select(q);
+
+			final List<Artist> result = ObjectSelect.query(Artist.class)
+					.prefetch(Artist.PAINTING_ARRAY.disjoint())
+					.select(context);
 
 			queryInterceptor.runWithQueriesBlocked(() -> {
 				assertFalse(result.isEmpty());
@@ -358,11 +360,10 @@ public class DataContextPrefetchIT extends ServerCase {
 
 		try {
 
-			SelectQuery<Artist> q = new SelectQuery<>(Artist.class);
-			q.setQualifier(ExpressionFactory.matchExp("artistName", "artist2"));
-			q.addPrefetch(Artist.PAINTING_ARRAY.disjoint());
-
-			final List<Artist> result = context.select(q);
+			final List<Artist> result = ObjectSelect.query(Artist.class)
+					.where(Artist.ARTIST_NAME.eq("artist2"))
+					.prefetch(Artist.PAINTING_ARRAY.disjoint())
+					.select(context);
 
 			queryInterceptor.runWithQueriesBlocked(() -> {
 				assertFalse(result.isEmpty());
@@ -381,10 +382,10 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetch_ToOne() throws Exception {
 		createTwoArtistsAndTwoPaintingsDataSet();
 
-		SelectQuery<Painting> q = new SelectQuery<>(Painting.class);
-		q.addPrefetch(Painting.TO_ARTIST.disjoint());
+		ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+				.prefetch(Painting.TO_ARTIST.disjoint());
 
-		final List<Painting> result = context.select(q);
+		final List<Painting> result = q.select(context);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
 			assertFalse(result.isEmpty());
@@ -404,11 +405,11 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetch_ToOne_DbPath() throws Exception {
 		createTwoArtistsAndTwoPaintingsDataSet();
 
-		SelectQuery<Painting> q = new SelectQuery<>(Painting.class);
-		q.addPrefetch(Painting.TO_ARTIST.disjoint());
-		q.andQualifier(ExpressionFactory.matchDbExp("toArtist.ARTIST_NAME", "artist2"));
+		ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+				.prefetch(Painting.TO_ARTIST.disjoint())
+				.and(Painting.TO_ARTIST.dot(Artist.ARTIST_NAME).eq("artist2"));
 
-		List<Painting> results = context.select(q);
+		List<Painting> results = q.select(context);
 
 		assertEquals(1, results.size());
 	}
@@ -417,11 +418,11 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetch_ToOne_ObjPath() throws Exception {
 		createTwoArtistsAndTwoPaintingsDataSet();
 
-		SelectQuery<Painting> q = new SelectQuery<>(Painting.class);
-		q.addPrefetch(Painting.TO_ARTIST.disjoint());
-		q.andQualifier(ExpressionFactory.matchExp("toArtist.artistName", "artist2"));
+		ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+				.prefetch(Painting.TO_ARTIST.disjoint())
+				.and(Painting.TO_ARTIST.dot(Artist.ARTIST_NAME).eq("artist2"));
 
-		List<Painting> results = context.select(q);
+		List<Painting> results = q.select(context);
 		assertEquals(1, results.size());
 	}
 
@@ -434,11 +435,11 @@ public class DataContextPrefetchIT extends ServerCase {
 		child.setToParentGroup(parent);
 		context.commitChanges();
 
-		SelectQuery<ArtGroup> q = new SelectQuery<>("ArtGroup");
-		q.setQualifier(ExpressionFactory.matchExp("name", "child"));
-		q.addPrefetch("toParentGroup");
+		ObjectSelect<ArtGroup> q = ObjectSelect.query(ArtGroup.class)
+				.where(ArtGroup.NAME.eq("child"))
+				.prefetch("toParentGroup", PrefetchTreeNode.UNDEFINED_SEMANTICS);
 
-		final List<ArtGroup> results = context.select(q);
+		final List<ArtGroup> results = q.select(context);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
 			assertEquals(1, results.size());
@@ -456,12 +457,11 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetch_ToOneWithQualifierOverlappingPrefetchPath() throws Exception {
 		createTwoArtistsAndTwoPaintingsDataSet();
 
-		Expression exp = ExpressionFactory.matchExp("toArtist.artistName", "artist3");
-
-		SelectQuery<Painting> q = new SelectQuery<>(Painting.class, exp);
-		q.addPrefetch(Painting.TO_ARTIST.disjoint());
+		ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+				.where(Painting.TO_ARTIST.dot(Artist.ARTIST_NAME).eq("artist3"))
+				.prefetch(Painting.TO_ARTIST.disjoint());
 
-		final List<Painting> results = context.select(q);
+		final List<Painting> results = q.select(context);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
 			assertEquals(1, results.size());
@@ -491,10 +491,11 @@ public class DataContextPrefetchIT extends ServerCase {
 		Expression exp = PropertyFactory.createBase("groupArray+.name", String.class)
 				.eq("XX").orExp(Artist.ARTIST_NAME.eq("artist2"));
 
-		SelectQuery<Artist> q = new SelectQuery<>(Artist.class, exp);
-		q.addPrefetch(Artist.PAINTING_ARRAY.disjoint());
+		ObjectSelect<Artist> q = ObjectSelect.query(Artist.class)
+				.where(exp)
+				.prefetch(Artist.PAINTING_ARRAY.disjoint());
 
-		final List<Artist> results = context.select(q);
+		final List<Artist> results = q.select(context);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
 			assertEquals(1, results.size());
@@ -509,19 +510,22 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetch9() throws Exception {
 		createTwoArtistsAndTwoPaintingsDataSet();
 
-		Expression artistExp = ExpressionFactory.matchExp("artistName", "artist3");
-		SelectQuery<Artist> artistQuery = new SelectQuery<>(Artist.class, artistExp);
-		Artist artist1 = (Artist) context.performQuery(artistQuery).get(0);
+		Artist artist1 = ObjectSelect
+				.query(Artist.class)
+				.where(Artist.ARTIST_NAME.eq("artist3"))
+				.select(context)
+				.get(0);
 
 		// find the painting not matching the artist (this is the case where
 		// such prefetch
 		// at least makes sense)
 		Expression exp = ExpressionFactory.noMatchExp("toArtist", artist1);
 
-		SelectQuery<Painting> q = new SelectQuery<>(Painting.class, exp);
-		q.addPrefetch("toArtist");
+		ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+				.where(Painting.TO_ARTIST.eq(artist1))
+				.prefetch("toArtist", PrefetchTreeNode.UNDEFINED_SEMANTICS);
 
-		final List<Painting> results = context.select(q);
+		final List<Painting> results = q.select(context);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
 			assertEquals(1, results.size());
@@ -538,12 +542,12 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetch_OneToOneWithQualifier() throws Exception {
 		createArtistWithTwoPaintingsAndTwoInfosDataSet();
 
-		Expression e = ExpressionFactory.likeExp("toArtist.artistName", "a%");
-		SelectQuery<Painting> q = new SelectQuery<>(Painting.class, e);
-		q.addPrefetch(Painting.TO_PAINTING_INFO.disjoint());
-		q.addOrdering(Painting.PAINTING_TITLE.asc());
+		ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+				.where(Painting.TO_ARTIST.dot(Artist.ARTIST_NAME).like("a%"))
+				.prefetch(Painting.TO_PAINTING_INFO.disjoint())
+				.orderBy(Painting.PAINTING_TITLE.asc());
 
-		final List<Painting> results = context.select(q);
+		final List<Painting> results = q.select(context);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
 			assertEquals(2, results.size());
@@ -570,9 +574,9 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetchToMany_DateInQualifier() throws Exception {
 		createTwoArtistsAndTwoPaintingsDataSet();
 
-		Expression e = ExpressionFactory.matchExp("dateOfBirth", new Date());
-		SelectQuery<Artist> q = new SelectQuery<>(Artist.class, e);
-		q.addPrefetch("paintingArray");
+		ObjectSelect<Artist> q = ObjectSelect.query(Artist.class)
+				.where(Artist.DATE_OF_BIRTH.eq(new Date()))
+				.prefetch("paintingArray", PrefetchTreeNode.UNDEFINED_SEMANTICS);
 
 		// prefetch with query using date in qualifier used to fail on SQL Server
 		// see CAY-119 for details
@@ -584,8 +588,8 @@ public class DataContextPrefetchIT extends ServerCase {
 
 		tPainting.insert(6, "p_Xty", null, 1000, null);
 
-		SelectQuery<Painting> q = new SelectQuery<>(Painting.class);
-		q.addPrefetch(Painting.TO_ARTIST.disjoint());
+		ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+				.prefetch(Painting.TO_ARTIST.disjoint());
 
 		final List<Painting> paintings = context.select(q);
 
@@ -601,9 +605,9 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetchToOneSharedCache() throws Exception {
 		createTwoArtistsAndTwoPaintingsDataSet();
 
-		SelectQuery<Painting> q = new SelectQuery<>(Painting.class);
-		q.addPrefetch(Painting.TO_ARTIST.disjoint());
-		q.setCacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+		ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+				.prefetch(Painting.TO_ARTIST.disjoint())
+				.cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
 
 		context.select(q);
 
@@ -634,9 +638,9 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetchToOneLocalCache() throws Exception {
 		createTwoArtistsAndTwoPaintingsDataSet();
 
-		final SelectQuery<Painting> q = new SelectQuery<>(Painting.class);
-		q.addPrefetch(Painting.TO_ARTIST.disjoint());
-		q.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+		ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+				.prefetch(Painting.TO_ARTIST.disjoint())
+				.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
 
 		context.select(q);
 
@@ -667,10 +671,10 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetchToOneWithBackRelationship() throws Exception {
 		createArtistWithTwoPaintingsAndTwoInfosDataSet();
 
-		SelectQuery<Painting> query = new SelectQuery<>(Painting.class);
-		query.andQualifier(Painting.PAINTING_TITLE.eq("p_artist2"));
-		query.addPrefetch(Painting.TO_PAINTING_INFO.disjoint());
-		query.addPrefetch(Painting.TO_PAINTING_INFO.dot(PaintingInfo.PAINTING).disjoint());
+		ObjectSelect<Painting> query = ObjectSelect.query(Painting.class)
+				.and(Painting.PAINTING_TITLE.eq("p_artist2"))
+				.prefetch(Painting.TO_PAINTING_INFO.disjoint())
+				.prefetch(Painting.TO_PAINTING_INFO.dot(PaintingInfo.PAINTING).disjoint());
 		final List<Painting> results = context.select(query);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
@@ -687,10 +691,10 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetchPaintingOverToOneAndToMany() throws Exception {
 		createArtistWithTwoPaintingsAndTwoInfosDataSet();
 
-		SelectQuery<Painting> query = new SelectQuery<Painting>(Painting.class);
-		query.andQualifier(Painting.PAINTING_TITLE.eq("p_artist2"));
-		query.addPrefetch(Painting.TO_ARTIST.disjoint());
-		query.addPrefetch(Painting.TO_ARTIST.dot(Artist.PAINTING_ARRAY).disjoint());
+		ObjectSelect<Painting> query = ObjectSelect.query(Painting.class)
+				.and(Painting.PAINTING_TITLE.eq("p_artist2"))
+				.prefetch(Painting.TO_ARTIST.disjoint())
+				.prefetch(Painting.TO_ARTIST.dot(Artist.PAINTING_ARRAY).disjoint());
 		final List<Painting> results = context.select(query);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
@@ -708,10 +712,10 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetchToOneWithBackRelationship_Joint() throws Exception {
 		createArtistWithTwoPaintingsAndTwoInfosDataSet();
 
-		SelectQuery<Painting> query = new SelectQuery<>(Painting.class);
-		query.andQualifier(Painting.PAINTING_TITLE.eq("p_artist2"));
-		query.addPrefetch(Painting.TO_PAINTING_INFO.joint());
-		query.addPrefetch(Painting.TO_PAINTING_INFO.dot(PaintingInfo.PAINTING).joint());
+		ObjectSelect<Painting> query = ObjectSelect.query(Painting.class)
+				.and(Painting.PAINTING_TITLE.eq("p_artist2"))
+				.prefetch(Painting.TO_PAINTING_INFO.joint())
+				.prefetch(Painting.TO_PAINTING_INFO.dot(PaintingInfo.PAINTING).joint());
 		final List<Painting> results = context.select(query);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
@@ -728,10 +732,10 @@ public class DataContextPrefetchIT extends ServerCase {
 	public void testPrefetchJointAndDisjointByIdTogether() throws Exception {
 		createArtistWithTwoPaintingsAndTwoInfosDataSet();
 
-		SelectQuery<Painting> query = new SelectQuery<>(Painting.class);
-		query.andQualifier(Painting.PAINTING_TITLE.eq("p_artist2"));
-		query.addPrefetch(Painting.TO_ARTIST.joint());
-		query.addPrefetch(Painting.TO_PAINTING_INFO.disjointById());
+		ObjectSelect<Painting> query = ObjectSelect.query(Painting.class)
+				.and(Painting.PAINTING_TITLE.eq("p_artist2"))
+				.prefetch(Painting.TO_ARTIST.joint())
+				.prefetch(Painting.TO_PAINTING_INFO.disjointById());
 		final List<Painting> results = context.select(query);
 
 		queryInterceptor.runWithQueriesBlocked(() -> {
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchQualifierOverlapIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchQualifierOverlapIT.java
index 1acdee4..ff3f4ac 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchQualifierOverlapIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextPrefetchQualifierOverlapIT.java
@@ -18,19 +18,20 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.util.List;
+
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Painting;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
 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.junit.Assert.assertEquals;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
@@ -61,12 +62,11 @@ public class DataContextPrefetchQualifierOverlapIT extends ServerCase {
     public void testToManyDisjointOverlappingQualifierWithInnerJoin() throws Exception {
         createTwoArtistsThreePaintingsDataSet();
 
-        SelectQuery query = new SelectQuery(Artist.class);
-        query.andQualifier(ExpressionFactory
-                .likeExp("paintingArray.paintingTitle", "AB%"));
-        query.addPrefetch(Artist.PAINTING_ARRAY.disjoint());
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                .and(Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE).like("AB%"))
+                .prefetch(Artist.PAINTING_ARRAY.disjoint());
 
-        List<Artist> result = context.performQuery(query);
+        List<Artist> result = query.select(context);
         assertEquals(1, result.size());
 
         Artist a = result.get(0);
@@ -77,12 +77,11 @@ public class DataContextPrefetchQualifierOverlapIT extends ServerCase {
     public void testToManyJointOverlappingQualifierWithInnerJoin() throws Exception {
         createTwoArtistsThreePaintingsDataSet();
 
-        SelectQuery query = new SelectQuery(Artist.class);
-        query.andQualifier(ExpressionFactory
-                .likeExp("paintingArray.paintingTitle", "AB%"));
-        query.addPrefetch(Artist.PAINTING_ARRAY.joint());
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                .and(Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE).like("AB%"))
+                .prefetch(Artist.PAINTING_ARRAY.joint());
 
-        List<Artist> result = context.performQuery(query);
+        List<Artist> result = query.select(context);
         assertEquals(1, result.size());
 
         Artist a = result.get(0);
@@ -93,16 +92,13 @@ public class DataContextPrefetchQualifierOverlapIT extends ServerCase {
     public void testToManyJointOverlappingQualifierWithOuterJoin() throws Exception {
         createTwoArtistsThreePaintingsDataSet();
 
-        SelectQuery query = new SelectQuery(Artist.class);
-        query.andQualifier(ExpressionFactory.likeExp(
-                "paintingArray+.paintingTitle",
-                "AB%"));
-        query.addPrefetch(Artist.PAINTING_ARRAY.joint());
-
-        query.orQualifier(ExpressionFactory.likeExp("artistName", "A%"));
-        query.addOrdering(Artist.ARTIST_NAME.asc());
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                .and(ExpressionFactory.likeExp("paintingArray+.paintingTitle", "AB%"))
+                .prefetch(Artist.PAINTING_ARRAY.joint())
+                .or(Artist.ARTIST_NAME.like("A%"))
+                .orderBy(Artist.ARTIST_NAME.asc());
 
-        List<Artist> result = context.performQuery(query);
+        List<Artist> result = query.select(context);
         assertEquals(2, result.size());
 
         Artist a = result.get(0);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextProcedureQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextProcedureQueryIT.java
index b11b622..3ac72e9 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextProcedureQueryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextProcedureQueryIT.java
@@ -19,14 +19,21 @@
 
 package org.apache.cayenne.access;
 
+import java.math.BigDecimal;
+import java.sql.Types;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.access.jdbc.ColumnDescriptor;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.log.JdbcEventLogger;
 import org.apache.cayenne.map.Procedure;
 import org.apache.cayenne.query.CapsStrategy;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.PrefetchTreeNode;
 import org.apache.cayenne.query.ProcedureQuery;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.testdo.testmap.Painting;
 import org.apache.cayenne.tx.BaseTransaction;
@@ -37,12 +44,6 @@ import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Test;
 
-import java.math.BigDecimal;
-import java.sql.Types;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -91,13 +92,13 @@ public class DataContextProcedureQueryIT extends ServerCase {
         }
 
         // check that price have doubled
-        SelectQuery select = new SelectQuery(Artist.class);
-        select.addPrefetch("paintingArray");
+        ObjectSelect<Artist> select = ObjectSelect.query(Artist.class)
+                .prefetch("paintingArray", PrefetchTreeNode.UNDEFINED_SEMANTICS);
 
-        List<?> artists = context.performQuery(select);
+        List<Artist> artists = select.select(context);
         assertEquals(1, artists.size());
 
-        Artist a = (Artist) artists.get(0);
+        Artist a = artists.get(0);
         Painting p = a.getPaintingArray().get(0);
         assertEquals(2000, p.getEstimatedPrice().intValue());
     }
@@ -127,13 +128,13 @@ public class DataContextProcedureQueryIT extends ServerCase {
         }
 
         // check that price have doubled
-        SelectQuery select = new SelectQuery(Artist.class);
-        select.addPrefetch("paintingArray");
+        ObjectSelect<Artist> select = ObjectSelect.query(Artist.class)
+                .prefetch("paintingArray", PrefetchTreeNode.UNDEFINED_SEMANTICS);
 
-        List<?> artists = context.performQuery(select);
+        List<Artist> artists = select.select(context);
         assertEquals(1, artists.size());
 
-        Artist a = (Artist) artists.get(0);
+        Artist a = artists.get(0);
         Painting p = a.getPaintingArray().get(0);
         assertEquals(2000, p.getEstimatedPrice().intValue());
     }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRefreshQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRefreshQueryIT.java
index e99c64c..49b2ed5 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRefreshQueryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRefreshQueryIT.java
@@ -18,14 +18,15 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.util.List;
+
 import org.apache.cayenne.Cayenne;
 import org.apache.cayenne.PersistenceState;
 import org.apache.cayenne.ValueHolder;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.QueryCacheStrategy;
 import org.apache.cayenne.query.RefreshQuery;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.query.SortOrder;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
@@ -37,8 +38,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.List;
-
 import static org.junit.Assert.*;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
@@ -91,12 +90,12 @@ public class DataContextRefreshQueryIT extends ServerCase {
     public void testRefreshCollection() throws Exception {
         createRefreshCollectionDataSet();
 
-        SelectQuery<Artist> q = new SelectQuery<>(Artist.class);
-        q.addOrdering("db:ARTIST_ID", SortOrder.ASCENDING);
-        List<?> artists = context.performQuery(q);
+        List<Artist> artists = ObjectSelect.query(Artist.class)
+                .orderBy("db:ARTIST_ID", SortOrder.ASCENDING)
+                .select(context);
 
-        Artist a1 = (Artist) artists.get(0);
-        Artist a2 = (Artist) artists.get(1);
+        Artist a1 = artists.get(0);
+        Artist a2 = artists.get(1);
 
         assertEquals(2, a1.getPaintingArray().size());
         assertEquals(0, a2.getPaintingArray().size());
@@ -135,12 +134,12 @@ public class DataContextRefreshQueryIT extends ServerCase {
     public void testRefreshCollectionToOne() throws Exception {
         createRefreshCollectionDataSet();
 
-        SelectQuery<Painting> q = new SelectQuery<>(Painting.class);
-        q.addOrdering("db:PAINTING_ID", SortOrder.ASCENDING);
-        List<?> paints = context.performQuery(q);
+        List<Painting> paints = ObjectSelect.query(Painting.class)
+                .orderBy("db:PAINTING_ID", SortOrder.ASCENDING)
+                .select(context);
 
-        Painting p1 = (Painting) paints.get(0);
-        Painting p2 = (Painting) paints.get(1);
+        Painting p1 = paints.get(0);
+        Painting p2 = paints.get(1);
 
         Artist a1 = p1.getToArtist();
         assertSame(a1, p2.getToArtist());
@@ -180,11 +179,11 @@ public class DataContextRefreshQueryIT extends ServerCase {
     public void testRefreshSingleObject() throws Exception {
         createRefreshCollectionDataSet();
 
-        SelectQuery<Artist> q = new SelectQuery<>(Artist.class);
-        q.addOrdering("db:ARTIST_ID", SortOrder.ASCENDING);
-        List<?> artists = context.performQuery(q);
+        List<Artist> artists = ObjectSelect.query(Artist.class)
+                .orderBy("db:ARTIST_ID", SortOrder.ASCENDING)
+                .select(context);
 
-        Artist a1 = (Artist) artists.get(0);
+        Artist a1 = artists.get(0);
 
         assertEquals(2, a1.getPaintingArray().size());
 
@@ -226,17 +225,18 @@ public class DataContextRefreshQueryIT extends ServerCase {
     public void testRefreshQueryResultsLocalCache() throws Exception {
         createRefreshCollectionDataSet();
 
-        Expression qual = Painting.PAINTING_TITLE.eq("P2");
-        SelectQuery<Painting> q = new SelectQuery<>(Painting.class, qual);
-        q.addOrdering("db:PAINTING_ID", SortOrder.ASCENDING);
-        q.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-        q.setCacheGroup("X");
-        List<?> paints = context.performQuery(q);
+        ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+                .where(Painting.PAINTING_TITLE.eq("P2"))
+                .orderBy("db:PAINTING_ID", SortOrder.ASCENDING)
+                .cacheStrategy(QueryCacheStrategy.LOCAL_CACHE)
+                .cacheGroup("X");
+
+        List<Painting> paints = q.select(context);
 
         // fetch P1 separately from cached query
         Painting p1 = Cayenne.objectForPK(context, Painting.class, 33001);
 
-        Painting p2 = (Painting) paints.get(0);
+        Painting p2 = paints.get(0);
         Artist a1 = p2.getToArtist();
         assertSame(a1, p1.getToArtist());
 
@@ -279,12 +279,12 @@ public class DataContextRefreshQueryIT extends ServerCase {
     public void testRefreshQueryResultsSharedCache() throws Exception {
         createRefreshCollectionDataSet();
 
-        Expression qual = Painting.PAINTING_TITLE.eq("P2");
-        SelectQuery<Painting> q = new SelectQuery<>(Painting.class, qual);
-        q.addOrdering("db:PAINTING_ID", SortOrder.ASCENDING);
-        q.setCacheStrategy(QueryCacheStrategy.SHARED_CACHE);
-        q.setCacheGroup("X");
-        List<?> paints = context.performQuery(q);
+        ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+                .where(Painting.PAINTING_TITLE.eq("P2"))
+                .orderBy("db:PAINTING_ID", SortOrder.ASCENDING)
+                .cacheStrategy(QueryCacheStrategy.SHARED_CACHE)
+                .cacheGroup("X");
+        List<?> paints = q.select(context);
 
         // fetch P1 separately from cached query
         Painting p1 = Cayenne.objectForPK(context, Painting.class, 33001);
@@ -332,17 +332,17 @@ public class DataContextRefreshQueryIT extends ServerCase {
     public void testRefreshQueryResultGroupLocal() throws Exception {
         createRefreshCollectionDataSet();
 
-        Expression qual = Painting.PAINTING_TITLE.eq("P2");
-        SelectQuery<Painting> q = new SelectQuery<>(Painting.class, qual);
-        q.addOrdering("db:PAINTING_ID", SortOrder.ASCENDING);
-        q.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-        q.setCacheGroup("X");
-        List<?> paints = context.performQuery(q);
+        ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+                .where(Painting.PAINTING_TITLE.eq("P2"))
+                .orderBy("db:PAINTING_ID", SortOrder.ASCENDING)
+                .cacheStrategy(QueryCacheStrategy.LOCAL_CACHE)
+                .cacheGroup("X");
+        List<Painting> paints = q.select(context);
 
         // fetch P1 separately from cached query
         Painting p1 = Cayenne.objectForPK(context, Painting.class, 33001);
 
-        Painting p2 = (Painting) paints.get(0);
+        Painting p2 = paints.get(0);
         Artist a1 = p2.getToArtist();
         assertSame(a1, p1.getToArtist());
 
@@ -385,13 +385,12 @@ public class DataContextRefreshQueryIT extends ServerCase {
     @Test
     public void testRefreshAll() throws Exception {
         createRefreshCollectionDataSet();
+        ObjectSelect<Artist> q = ObjectSelect.query(Artist.class)
+                .orderBy("db:ARTIST_ID", SortOrder.ASCENDING);
+        List<Artist> artists = q.select(context);
 
-        SelectQuery<Artist> q = new SelectQuery<>(Artist.class);
-        q.addOrdering("db:ARTIST_ID", SortOrder.ASCENDING);
-        List<?> artists = context.performQuery(q);
-
-        Artist a1 = (Artist) artists.get(0);
-        Artist a2 = (Artist) artists.get(1);
+        Artist a1 = artists.get(0);
+        Artist a2 = artists.get(1);
         Painting p1 = a1.getPaintingArray().get(0);
         Painting p2 = a1.getPaintingArray().get(0);
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRefreshingIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRefreshingIT.java
index 2e3eca7..2f48a76 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRefreshingIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRefreshingIT.java
@@ -19,26 +19,24 @@
 
 package org.apache.cayenne.access;
 
+import java.sql.Types;
+import java.util.Date;
+import java.util.List;
+
 import org.apache.cayenne.PersistenceState;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.testdo.testmap.Painting;
 import org.apache.cayenne.unit.di.DataChannelInterceptor;
-import org.apache.cayenne.unit.di.UnitTestClosure;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
 import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.sql.Types;
-import java.util.Date;
-import java.util.List;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
@@ -109,9 +107,8 @@ public class DataContextRefreshingIT extends ServerCase {
         String nameBefore = "artist2";
         String nameAfter = "not an artist";
 
-        SelectQuery queryBefore = new SelectQuery(
-                Artist.class,
-                ExpressionFactory.matchExp("artistName", nameBefore));
+        ObjectSelect<Artist> queryBefore = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.eq(nameBefore));
 
         Artist artist = (Artist) context.performQuery(queryBefore).get(0);
         assertEquals(nameBefore, artist.getArtistName());
@@ -119,12 +116,11 @@ public class DataContextRefreshingIT extends ServerCase {
         assertEquals(1, tArtist.update().set("ARTIST_NAME", nameAfter).execute());
 
         // fetch into the same context
-        List<Artist> artists = context.performQuery(queryBefore);
+        List<Artist> artists = queryBefore.select(context);
         assertEquals(0, artists.size());
 
-        SelectQuery queryAfter = new SelectQuery(
-                Artist.class,
-                ExpressionFactory.matchExp("artistName", nameAfter));
+        ObjectSelect<Artist> queryAfter = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.eq(nameAfter));
 
         artist = (Artist) context.performQuery(queryAfter).get(0);
         assertNotNull(artist);
@@ -136,7 +132,7 @@ public class DataContextRefreshingIT extends ServerCase {
         createSingleArtistAndPaintingDataSet();
 
         Painting painting = (Painting) context.performQuery(
-                new SelectQuery(Painting.class)).get(0);
+                ObjectSelect.query(Painting.class)).get(0);
 
         assertNotNull(painting.getToArtist());
         assertEquals("artist2", painting.getToArtist().getArtistName());
@@ -145,7 +141,7 @@ public class DataContextRefreshingIT extends ServerCase {
 
         // select without prefetch
         painting = (Painting) context
-                .performQuery(new SelectQuery(Painting.class))
+                .performQuery(ObjectSelect.query(Painting.class))
                 .get(0);
         assertNotNull(painting);
         assertNull(painting.getToArtist());
@@ -156,7 +152,7 @@ public class DataContextRefreshingIT extends ServerCase {
         createTwoArtistsAndPaintingDataSet();
 
         Painting painting = (Painting) context.performQuery(
-                new SelectQuery(Painting.class)).get(0);
+                ObjectSelect.query(Painting.class)).get(0);
 
         Artist artistBefore = painting.getToArtist();
         assertNotNull(artistBefore);
@@ -166,7 +162,7 @@ public class DataContextRefreshingIT extends ServerCase {
 
         // select without prefetch
         painting = (Painting) context
-                .performQuery(new SelectQuery(Painting.class))
+                .performQuery(ObjectSelect.query(Painting.class))
                 .get(0);
         assertNotNull(painting);
         assertEquals("artist3", painting.getToArtist().getArtistName());
@@ -177,7 +173,7 @@ public class DataContextRefreshingIT extends ServerCase {
         createSingleArtistAndUnrelatedPaintingDataSet();
 
         Painting painting = (Painting) context.performQuery(
-                new SelectQuery(Painting.class)).get(0);
+                ObjectSelect.query(Painting.class)).get(0);
 
         assertNull(painting.getToArtist());
 
@@ -185,7 +181,7 @@ public class DataContextRefreshingIT extends ServerCase {
 
         // select without prefetch
         painting = (Painting) context
-                .performQuery(new SelectQuery(Painting.class))
+                .performQuery(ObjectSelect.query(Painting.class))
                 .get(0);
         assertNotNull(painting);
         assertEquals("artist2", painting.getToArtist().getArtistName());
@@ -195,7 +191,7 @@ public class DataContextRefreshingIT extends ServerCase {
     public void testRefetchRootWithDeletedToMany() throws Exception {
         createSingleArtistAndPaintingDataSet();
 
-        Artist artist = (Artist) context.performQuery(new SelectQuery(Artist.class)).get(
+        Artist artist = (Artist) context.performQuery(ObjectSelect.query(Artist.class)).get(
                 0);
         assertEquals(artist.getPaintingArray().size(), 1);
 
@@ -205,12 +201,12 @@ public class DataContextRefreshingIT extends ServerCase {
                 .execute());
 
         // select without prefetch
-        artist = (Artist) context.performQuery(new SelectQuery(Artist.class)).get(0);
+        artist = (Artist) context.performQuery(ObjectSelect.query(Artist.class)).get(0);
         assertEquals(artist.getPaintingArray().size(), 1);
 
         // select using relationship prefetching
-        SelectQuery query = new SelectQuery(Artist.class);
-        query.addPrefetch(Artist.PAINTING_ARRAY.disjoint());
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                .prefetch(Artist.PAINTING_ARRAY.disjoint());
         artist = (Artist) context.performQuery(query).get(0);
         assertEquals(0, artist.getPaintingArray().size());
     }
@@ -220,19 +216,19 @@ public class DataContextRefreshingIT extends ServerCase {
 
         createSingleArtistDataSet();
 
-        Artist artist = (Artist) context.performQuery(new SelectQuery(Artist.class)).get(
+        Artist artist = (Artist) context.performQuery(ObjectSelect.query(Artist.class)).get(
                 0);
         assertEquals(artist.getPaintingArray().size(), 0);
 
         tPainting.insert(5, "p", 5, 1000);
 
         // select without prefetch
-        SelectQuery query = new SelectQuery(Artist.class);
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class);
         artist = (Artist) context.performQuery(query).get(0);
         assertEquals(artist.getPaintingArray().size(), 0);
 
         // select using relationship prefetching
-        query.addPrefetch(Artist.PAINTING_ARRAY.disjoint());
+        query.prefetch(Artist.PAINTING_ARRAY.disjoint());
         artist = (Artist) context.performQuery(query).get(0);
         assertEquals(artist.getPaintingArray().size(), 1);
     }
@@ -244,8 +240,7 @@ public class DataContextRefreshingIT extends ServerCase {
         String nameBefore = "artist2";
         String nameAfter = "not an artist";
 
-        Artist artist = (Artist) context.performQuery(new SelectQuery(Artist.class)).get(
-                0);
+        Artist artist = (Artist) context.performQuery(ObjectSelect.query(Artist.class)).get(0);
         assertNotNull(artist);
         assertEquals(nameBefore, artist.getArtistName());
 
@@ -261,8 +256,7 @@ public class DataContextRefreshingIT extends ServerCase {
 
         createSingleArtistAndPaintingDataSet();
 
-        Painting painting = (Painting) context.performQuery(
-                new SelectQuery(Painting.class)).get(0);
+        Painting painting = (Painting) context.performQuery(ObjectSelect.query(Painting.class)).get(0);
 
         assertNotNull(painting.getToArtist());
         assertEquals("artist2", painting.getToArtist().getArtistName());
@@ -278,7 +272,7 @@ public class DataContextRefreshingIT extends ServerCase {
         createTwoArtistsAndPaintingDataSet();
 
         Painting painting = (Painting) context.performQuery(
-                new SelectQuery(Painting.class)).get(0);
+                ObjectSelect.query(Painting.class)).get(0);
         Artist artistBefore = painting.getToArtist();
         assertNotNull(artistBefore);
         assertEquals("artist2", artistBefore.getArtistName());
@@ -295,7 +289,7 @@ public class DataContextRefreshingIT extends ServerCase {
         createSingleArtistAndUnrelatedPaintingDataSet();
 
         Painting painting = (Painting) context.performQuery(
-                new SelectQuery(Painting.class)).get(0);
+                ObjectSelect.query(Painting.class)).get(0);
         assertNull(painting.getToArtist());
 
         assertEquals(1, tPainting.update().set("ARTIST_ID", 5).execute());
@@ -309,8 +303,7 @@ public class DataContextRefreshingIT extends ServerCase {
     public void testInvalidateRootWithDeletedToMany() throws Exception {
         createSingleArtistAndPaintingDataSet();
 
-        Artist artist = (Artist) context.performQuery(new SelectQuery(Artist.class)).get(
-                0);
+        Artist artist = (Artist) context.performQuery(ObjectSelect.query(Artist.class)).get(0);
         assertEquals(artist.getPaintingArray().size(), 1);
 
         assertEquals(1, tPainting.delete().execute());
@@ -324,8 +317,7 @@ public class DataContextRefreshingIT extends ServerCase {
 
         createSingleArtistDataSet();
 
-        Artist artist = (Artist) context.performQuery(new SelectQuery(Artist.class)).get(
-                0);
+        Artist artist = (Artist) context.performQuery(ObjectSelect.query(Artist.class)).get(0);
         assertEquals(artist.getPaintingArray().size(), 0);
 
         tPainting.insert(4, "p", 5, 1000);
@@ -341,19 +333,16 @@ public class DataContextRefreshingIT extends ServerCase {
         createSingleArtistDataSet();
 
         final Artist artist = (Artist) context
-                .performQuery(new SelectQuery(Artist.class))
+                .performQuery(ObjectSelect.query(Artist.class))
                 .get(0);
         assertNotNull(artist);
 
         context.invalidateObjects(artist);
         assertEquals(PersistenceState.HOLLOW, artist.getPersistenceState());
 
-        int queries = queryInterceptor.runWithQueryCounter(new UnitTestClosure() {
-
-            public void execute() {
-                // this must trigger a fetch
-                artist.setArtistName("new name");
-            }
+        int queries = queryInterceptor.runWithQueryCounter(() -> {
+            // this must trigger a fetch
+            artist.setArtistName("new name");
         });
 
         assertEquals(1, queries);
@@ -365,18 +354,15 @@ public class DataContextRefreshingIT extends ServerCase {
 
         createSingleArtistAndPaintingDataSet();
 
-        Painting painting = (Painting) context.performQuery(
-                new SelectQuery(Painting.class)).get(0);
+        Painting painting = (Painting) context
+                .performQuery(ObjectSelect.query(Painting.class)).get(0);
         final Artist artist = painting.getToArtist();
         assertEquals(PersistenceState.HOLLOW, artist.getPersistenceState());
         assertNull(artist.readPropertyDirectly("artistName"));
 
-        int queries = queryInterceptor.runWithQueryCounter(new UnitTestClosure() {
-
-            public void execute() {
-                // this must trigger a fetch
-                artist.setDateOfBirth(new Date());
-            }
+        int queries = queryInterceptor.runWithQueryCounter(() -> {
+            // this must trigger a fetch
+            artist.setDateOfBirth(new Date());
         });
 
         assertEquals(1, queries);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRollbackIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRollbackIT.java
index c0a607f..dae27d3 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRollbackIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextRollbackIT.java
@@ -19,12 +19,13 @@
 
 package org.apache.cayenne.access;
 
+import java.util.List;
+
 import org.apache.cayenne.PersistenceState;
 import org.apache.cayenne.ValueHolder;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.testdo.testmap.Painting;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
@@ -32,8 +33,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.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
@@ -90,9 +89,9 @@ public class DataContextRollbackIT extends ServerCase {
         DataContext freshContext = (DataContext) serverRuntime.newContext();
         assertNotSame(this.context, freshContext);
 
-        SelectQuery query = new SelectQuery(Artist.class);
-        query.setQualifier(ExpressionFactory.matchExp("artistName", artistName));
-        List<?> queryResults = freshContext.performQuery(query);
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.eq(artistName));
+        List<Artist> queryResults = query.select(freshContext);
 
         assertEquals(0, queryResults.size());
     }
@@ -122,9 +121,9 @@ public class DataContextRollbackIT extends ServerCase {
         DataContext freshContext = (DataContext) serverRuntime.newContext();
         assertNotSame(this.context, freshContext);
 
-        SelectQuery query = new SelectQuery(Artist.class);
-        query.setQualifier(ExpressionFactory.matchExp("artistName", artistName));
-        List<?> queryResults = freshContext.performQuery(query);
+        List<?> queryResults = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.eq(artistName))
+                .select(freshContext);
 
         assertEquals(0, queryResults.size());
     }
@@ -155,9 +154,9 @@ public class DataContextRollbackIT extends ServerCase {
         DataContext freshContext = (DataContext) serverRuntime.newContext();
         assertNotSame(this.context, freshContext);
 
-        SelectQuery query = new SelectQuery(Painting.class);
-        query.setQualifier(ExpressionFactory.matchExp("paintingTitle", paintingTitle));
-        List<?> queryResults = freshContext.performQuery(query);
+        List<?> queryResults = ObjectSelect.query(Painting.class)
+                .where(Painting.PAINTING_TITLE.eq(paintingTitle))
+                .select(freshContext);
 
         assertEquals(1, queryResults.size());
         Painting queriedPainting = (Painting) queryResults.get(0);
@@ -172,7 +171,7 @@ public class DataContextRollbackIT extends ServerCase {
         Artist artist = (Artist) context.newObject("Artist");
         artist.setArtistName(artistName);
         context.commitChanges();
-       
+
         context.deleteObjects(artist);
         context.rollbackChanges();
 
@@ -186,9 +185,9 @@ public class DataContextRollbackIT extends ServerCase {
         DataContext freshContext = (DataContext) serverRuntime.newContext();
         assertNotSame(this.context, freshContext);
 
-        SelectQuery query = new SelectQuery(Artist.class);
-        query.setQualifier(ExpressionFactory.matchExp("artistName", artistName));
-        List<?> queryResults = freshContext.performQuery(query);
+        List<?> queryResults = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.eq(artistName))
+                .select(context);
 
         assertEquals(1, queryResults.size());
     }
@@ -214,9 +213,9 @@ public class DataContextRollbackIT extends ServerCase {
         DataContext freshContext = (DataContext) serverRuntime.newContext();
         assertNotSame(this.context, freshContext);
 
-        SelectQuery query = new SelectQuery(Artist.class);
-        query.setQualifier(ExpressionFactory.matchExp("artistName", artistName));
-        List<?> queryResults = freshContext.performQuery(query);
+        List<?> queryResults = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.eq(artistName))
+                .select(freshContext);
 
         assertEquals(1, queryResults.size());
     }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheEmpiricIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheEmpiricIT.java
index 2ba1e07..8fe5541 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheEmpiricIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheEmpiricIT.java
@@ -28,7 +28,7 @@ import org.apache.cayenne.configuration.ObjectStoreFactory;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.event.DefaultEventManager;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.test.parallel.ParallelTestContainer;
@@ -41,8 +41,8 @@ import org.junit.Before;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
 public class DataContextSharedCacheEmpiricIT extends ServerCaseContextsSync {
@@ -51,7 +51,7 @@ public class DataContextSharedCacheEmpiricIT extends ServerCaseContextsSync {
 
     @Inject
     private ServerRuntime runtime;
-    
+
     @Inject
     private ObjectStoreFactory objectStoreFactory;
 
@@ -71,9 +71,9 @@ public class DataContextSharedCacheEmpiricIT extends ServerCaseContextsSync {
                 new DefaultRuntimeProperties(Collections.<String, String>emptyMap()),
                 eventManager);
 
-        c1 = new DataContext(runtime.getDataDomain(), 
+        c1 = new DataContext(runtime.getDataDomain(),
                 objectStoreFactory.createObjectStore(cache));
-        c2 = new DataContext(runtime.getDataDomain(), 
+        c2 = new DataContext(runtime.getDataDomain(),
                 objectStoreFactory.createObjectStore(cache));
 
         // prepare a single artist record
@@ -92,16 +92,16 @@ public class DataContextSharedCacheEmpiricIT extends ServerCaseContextsSync {
     @Test
     public void testSelectSelectCommitRefresh() throws Exception {
 
-        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class);
 
         // select both, a2 should go second...
-        List<?> artists = c1.performQuery(query);
-        Artist a1 = (Artist) artists.get(0);
+        List<Artist> artists = query.select(c1);
+        Artist a1 = artists.get(0);
 
-        List<?> altArtists = c2.performQuery(query);
-        final Artist a2 = (Artist) altArtists.get(0);
+        List<Artist> altArtists = query.select(c2);
+        final Artist a2 = altArtists.get(0);
         assertNotNull(a2);
-        assertFalse(a2 == a1);
+        assertNotSame(a2, a1);
 
         // Update Artist
         a1.setArtistName(NEW_NAME);
@@ -113,15 +113,15 @@ public class DataContextSharedCacheEmpiricIT extends ServerCaseContextsSync {
     @Test
     public void testSelectSelectCommitRefreshReverse() throws Exception {
 
-        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class);
 
-        List<?> altArtists = c2.performQuery(query);
-        final Artist a2 = (Artist) altArtists.get(0);
+        List<Artist> altArtists = query.select(c2);
+        final Artist a2 = altArtists.get(0);
 
         List<?> artists = c1.performQuery(query);
         Artist a1 = (Artist) artists.get(0);
 
-        assertFalse(a2 == a1);
+        assertNotSame(a2, a1);
 
         // Update Artist
         a1.setArtistName(NEW_NAME);
@@ -133,18 +133,18 @@ public class DataContextSharedCacheEmpiricIT extends ServerCaseContextsSync {
     @Test
     public void testSelectUpdateSelectCommitRefresh() throws Exception {
 
-        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class);
 
-        List<?> artists = c1.performQuery(query);
-        Artist a1 = (Artist) artists.get(0);
+        List<Artist> artists = query.select(c1);
+        Artist a1 = artists.get(0);
 
         // Update Artist
         a1.setArtistName(NEW_NAME);
 
-        List<?> altArtists = c2.performQuery(query);
-        final Artist a2 = (Artist) altArtists.get(0);
+        List<Artist> altArtists = query.select(c2);
+        final Artist a2 = altArtists.get(0);
         assertNotNull(a2);
-        assertFalse(a2 == a1);
+        assertNotSame(a2, a1);
 
         c1.commitChanges();
         assertOnCommit(a2);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheIT.java
index a7cb1ff..518bc85 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheIT.java
@@ -29,10 +29,8 @@ import org.apache.cayenne.DataRow;
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.PersistenceState;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.SQLTemplate;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.test.parallel.ParallelTestContainer;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.testdo.testmap.Painting;
@@ -43,13 +41,7 @@ import org.apache.cayenne.unit.util.SQLTemplateCustomizer;
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 /**
  * Test suite for testing behavior of multiple DataContexts that share the same underlying
@@ -101,10 +93,11 @@ public class DataContextSharedCacheIT extends ServerCaseContextsSync {
 
         // fetch updated artist into the new context, and see if the original
         // one gets updated
-        Expression qual = ExpressionFactory.matchExp("artistName", newName);
-        List artists = context1.performQuery(new SelectQuery<>(Artist.class, qual));
+        List<Artist> artists = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.eq(newName))
+                .select(context);
         assertEquals(1, artists.size());
-        Artist altArtist = (Artist) artists.get(0);
+        Artist altArtist = artists.get(0);
 
         // check underlying cache
         DataRow freshSnapshot = context
@@ -539,9 +532,9 @@ public class DataContextSharedCacheIT extends ServerCaseContextsSync {
         context.performNonSelectingQuery(update);
 
         // fetch updated artist without refreshing
-        Expression qual = ExpressionFactory.matchExp("artistName", newName);
-        SelectQuery query = new SelectQuery<>(Artist.class, qual);
-        List artists = context.performQuery(query);
+        List artists = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.eq(newName))
+                .select(context);
         assertEquals(1, artists.size());
         artist = (Artist) artists.get(0);
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainCallbacksIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainCallbacksIT.java
index 9e06b84..eb4df07 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainCallbacksIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainCallbacksIT.java
@@ -25,8 +25,8 @@ import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.map.LifecycleEvent;
 import org.apache.cayenne.query.EJBQLQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.RefreshQuery;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.reflect.LifecycleCallbackRegistry;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.testdo.testmap.Painting;
@@ -35,11 +35,7 @@ import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
 public class DataDomainCallbacksIT extends ServerCase {
@@ -71,8 +67,7 @@ public class DataDomainCallbacksIT extends ServerCase {
         assertEquals(0, a1.getPostLoaded());
         assertNull(listener.getPublicCalledbackEntity());
 
-        SelectQuery q = new SelectQuery(Artist.class);
-        context.performQuery(q);
+        ObjectSelect.query(Artist.class).select(context);
         assertEquals(1, a1.getPostLoaded());
         assertSame(a1, listener.getPublicCalledbackEntity());
 
@@ -153,8 +148,7 @@ public class DataDomainCallbacksIT extends ServerCase {
 
         context.invalidateObjects(a1, p1);
 
-        SelectQuery q = new SelectQuery(Painting.class);
-        p1 = (Painting) context1.performQuery(q).get(0);
+        p1 = ObjectSelect.query(Painting.class).select(context).get(0);
 
         // this should be a hollow object, so no callback just yet
         a1 = p1.getToArtist();
@@ -186,9 +180,9 @@ public class DataDomainCallbacksIT extends ServerCase {
         p1.setPaintingTitle("XXX");
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(Painting.class);
-        q.addPrefetch(Painting.TO_ARTIST.disjoint());
-        p1 = (Painting) context1.performQuery(q).get(0);
+        p1 = ObjectSelect.query(Painting.class)
+                .prefetch(Painting.TO_ARTIST.disjoint())
+                .select(context).get(0);
 
         // artist is prefetched here, and a callback must have been invoked
         a1 = p1.getToArtist();
@@ -252,8 +246,8 @@ public class DataDomainCallbacksIT extends ServerCase {
 
         context.invalidateObjects(a1, p1);
 
-        SelectQuery<Painting> q = new SelectQuery<>(Painting.class);
-        p1 = q.select(context1).get(0);
+        p1 = ObjectSelect.query(Painting.class)
+                .select(context1).get(0);
 
         // this should be a hollow object, so no callback just yet
         a1 = p1.getToArtist();
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainFiltersIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainFiltersIT.java
index 59a83d1..62964f4 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainFiltersIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainFiltersIT.java
@@ -18,6 +18,9 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.cayenne.DataChannelQueryFilter;
 import org.apache.cayenne.DataChannelQueryFilterChain;
 import org.apache.cayenne.DataChannelSyncFilter;
@@ -28,8 +31,8 @@ import org.apache.cayenne.annotation.PostPersist;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.graph.GraphDiff;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.Query;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
 import org.apache.cayenne.unit.di.server.ServerCase;
@@ -37,9 +40,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.apache.cayenne.util.ListResponse;
 import org.junit.Test;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
@@ -84,7 +84,7 @@ public class DataDomainFiltersIT extends ServerCase {
         domain.queryFilters.add(f1);
         domain.queryFilters.add(f2);
 
-        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class);
         QueryResponse response = domain.onQuery(context, query);
         assertNotNull(response);
         assertEquals(4, results.size());
@@ -144,7 +144,7 @@ public class DataDomainFiltersIT extends ServerCase {
         domain.queryFilters.add(f1);
         domain.queryFilters.add(f2);
 
-        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class);
         QueryResponse response = domain.onQuery(context, query);
 
         assertSame(r2, response);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainQueryActionIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainQueryActionIT.java
index e31abc1..13ce174 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainQueryActionIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainQueryActionIT.java
@@ -18,14 +18,17 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.io.Serializable;
+import java.util.List;
+
 import org.apache.cayenne.cache.MockQueryCache;
 import org.apache.cayenne.cache.QueryCache;
 import org.apache.cayenne.cache.QueryCacheEntryFactory;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.QueryCacheStrategy;
 import org.apache.cayenne.query.QueryMetadata;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.testdo.testmap.Painting;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
 import org.apache.cayenne.unit.di.server.ServerCase;
@@ -33,9 +36,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.After;
 import org.junit.Test;
 
-import java.io.Serializable;
-import java.util.List;
-
 import static org.junit.Assert.assertTrue;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
@@ -60,13 +60,12 @@ public class DataDomainQueryActionIT extends ServerCase {
         Painting p = context.newObject(Painting.class);
         p.setPaintingTitle("sample");
 
-        SelectQuery query = new SelectQuery(Painting.class);
-
-        query.addPrefetch(Painting.TO_GALLERY.disjoint());
-        query.addPrefetch(Painting.TO_ARTIST.disjoint());
-        query.addOrdering(Painting.PAINTING_TITLE.asc());
-        query.setCacheStrategy(QueryCacheStrategy.SHARED_CACHE);
-        query.setPageSize(5);
+        ObjectSelect<Painting> query = ObjectSelect.query(Painting.class)
+                .prefetch(Painting.TO_GALLERY.disjoint())
+                .prefetch(Painting.TO_ARTIST.disjoint())
+                .orderBy(Painting.PAINTING_TITLE.asc())
+                .cacheStrategy(QueryCacheStrategy.SHARED_CACHE)
+                .pageSize(5);
 
         QueryCache cache = domain.queryCache;
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataRowUtilsIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataRowUtilsIT.java
index b67abb7..39db247 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataRowUtilsIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataRowUtilsIT.java
@@ -19,9 +19,11 @@
 
 package org.apache.cayenne.access;
 
+import java.util.List;
+
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.reflect.ArcProperty;
 import org.apache.cayenne.reflect.ClassDescriptor;
 import org.apache.cayenne.test.jdbc.DBHelper;
@@ -35,9 +37,10 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.List;
-
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
 public class DataRowUtilsIT extends ServerCase {
@@ -80,8 +83,9 @@ public class DataRowUtilsIT extends ServerCase {
         String n1 = "changed";
         String n2 = "changed again";
 
-        SelectQuery artistQ = new SelectQuery(Artist.class);
-        Artist a1 = (Artist) context.performQuery(artistQ).get(0);
+        Artist a1 = ObjectSelect.query(Artist.class)
+                .select(context)
+                .get(0);
         a1.setArtistName(n1);
 
         DataRow s2 = new DataRow(2);
@@ -105,9 +109,7 @@ public class DataRowUtilsIT extends ServerCase {
         ClassDescriptor d = context.getEntityResolver().getClassDescriptor("Painting");
         ArcProperty toArtist = (ArcProperty) d.getProperty("toArtist");
 
-        Artist artist2 = (Artist) context
-                .performQuery(new SelectQuery(Artist.class))
-                .get(0);
+        Artist artist2 = ObjectSelect.query(Artist.class).selectFirst(context);
         Painting painting = context.newObject(Painting.class);
         painting.setPaintingTitle("PX");
         painting.setToArtist(artist2);
@@ -115,8 +117,9 @@ public class DataRowUtilsIT extends ServerCase {
         context.commitChanges();
 
         tArtist.insert(119, "artist3");
-        SelectQuery query = new SelectQuery(Artist.class, Artist.ARTIST_NAME.eq("artist3"));
-        Artist artist3 = (Artist) context.performQuery(query).get(0);
+        Artist artist3 = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.eq("artist3"))
+                .selectFirst(context);
         assertNotSame(artist3, painting.getToArtist());
 
         ObjectDiff diff = context.getObjectStore().registerDiff(
@@ -134,7 +137,7 @@ public class DataRowUtilsIT extends ServerCase {
         createOneArtistAndOnePainting();
 
         // add NEW gallery to painting
-        List<Painting> paintings = context.performQuery(new SelectQuery(Painting.class));
+        List<Painting> paintings = ObjectSelect.query(Painting.class).select(context);
         assertEquals(1, paintings.size());
         Painting p1 = paintings.get(0);
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DateTimeTypesIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DateTimeTypesIT.java
index bdc0db3..2031afa 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DateTimeTypesIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DateTimeTypesIT.java
@@ -19,10 +19,14 @@
 
 package org.apache.cayenne.access;
 
+import java.sql.Time;
+import java.util.Calendar;
+import java.util.Date;
+
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.query.MappedSelect;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.testdo.date_time.CalendarEntity;
 import org.apache.cayenne.testdo.date_time.DateTestEntity;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
@@ -30,10 +34,6 @@ import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Test;
 
-import java.sql.Time;
-import java.util.Calendar;
-import java.util.Date;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -59,8 +59,8 @@ public class DateTimeTypesIT extends ServerCase {
         test.setCalendarField(cal);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(CalendarEntity.class);
-        CalendarEntity testRead = (CalendarEntity) context.performQuery(q).get(0);
+        CalendarEntity testRead = ObjectSelect.query(CalendarEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getCalendarField());
         assertEquals(cal, testRead.getCalendarField());
 
@@ -79,8 +79,8 @@ public class DateTimeTypesIT extends ServerCase {
         test.setDateColumn(nowDate);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(DateTestEntity.class);
-        DateTestEntity testRead = (DateTestEntity) context.performQuery(q).get(0);
+        DateTestEntity testRead = ObjectSelect.query(DateTestEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getDateColumn());
         assertEquals(nowDate, testRead.getDateColumn());
         assertEquals(Date.class, testRead.getDateColumn().getClass());
@@ -97,8 +97,8 @@ public class DateTimeTypesIT extends ServerCase {
         test.setTimeColumn(nowTime);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(DateTestEntity.class);
-        DateTestEntity testRead = (DateTestEntity) context.performQuery(q).get(0);
+        DateTestEntity testRead = ObjectSelect.query(DateTestEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getTimeColumn());
         assertEquals(Date.class, testRead.getTimeColumn().getClass());
 
@@ -126,8 +126,8 @@ public class DateTimeTypesIT extends ServerCase {
         test.setTimestampColumn(now);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(DateTestEntity.class);
-        DateTestEntity testRead = (DateTestEntity) context.performQuery(q).get(0);
+        DateTestEntity testRead = ObjectSelect.query(DateTestEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getTimestampColumn());
         assertEquals(now, testRead.getTimestampColumn());
     }
@@ -146,7 +146,7 @@ public class DateTimeTypesIT extends ServerCase {
         Date now = cal.getTime();
         test.setTimestampColumn(now);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectDateTest")).get(0);
         Date columnValue = (Date) testRead.get("TIMESTAMP_COLUMN");
         assertNotNull(columnValue);
@@ -167,7 +167,7 @@ public class DateTimeTypesIT extends ServerCase {
         java.sql.Date now = new java.sql.Date(cal.getTime().getTime());
         test.setDateColumn(now);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectDateTest")).get(0);
         Date columnValue = (Date) testRead.get("DATE_COLUMN");
         assertNotNull(columnValue);
@@ -188,7 +188,7 @@ public class DateTimeTypesIT extends ServerCase {
         Time now = new Time(cal.getTime().getTime());
         test.setTimeColumn(now);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectDateTest")).get(0);
         Date columnValue = (Date) testRead.get("TIME_COLUMN");
         assertNotNull(testRead.toString(), columnValue);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/EnumIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/EnumIT.java
index a294173..f25d704 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/EnumIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/EnumIT.java
@@ -67,6 +67,7 @@ public class EnumIT extends ServerCase {
     }
 
     @Test
+    @Deprecated
     public void testSelectQuery() throws Exception {
         createDataSet();
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/FlattenedPrefetchIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/FlattenedPrefetchIT.java
index 4d16b78..a087c8c 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/FlattenedPrefetchIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/FlattenedPrefetchIT.java
@@ -19,11 +19,15 @@
 
 package org.apache.cayenne.access;
 
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.PersistenceState;
 import org.apache.cayenne.ValueHolder;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.testmap.ArtGroup;
@@ -36,11 +40,10 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
 public class FlattenedPrefetchIT extends ServerCase {
@@ -97,10 +100,10 @@ public class FlattenedPrefetchIT extends ServerCase {
         tArtist.insert(33001, "artist1");
         tArtist.insert(33002, "artist2");
         tArtist.insert(33003, "artist3");
-        
+
         tArtgroup.insert(33001, "group1");
         tArtgroup.insert(33002, "group2");
-      
+
         tArtistGroup.insert(33001, 33001);
         tArtistGroup.insert(33001, 33002);
         tArtistGroup.insert(33002, 33002);
@@ -114,10 +117,9 @@ public class FlattenedPrefetchIT extends ServerCase {
     public void testManyToMany() throws Exception {
         createPrefetchDataSet1();
 
-        SelectQuery<Artist> q = new SelectQuery<>(Artist.class);
-        q.addPrefetch(Artist.GROUP_ARRAY.disjoint());
-
-        List<Artist> objects = context.select(q);
+        List<Artist> objects = ObjectSelect.query(Artist.class)
+                .prefetch(Artist.GROUP_ARRAY.disjoint())
+                .select(context);
 
         queryInterceptor.runWithQueriesBlocked(() -> assertArtistResult(objects));
     }
@@ -126,11 +128,10 @@ public class FlattenedPrefetchIT extends ServerCase {
     public void testMultiPrefetch() throws Exception {
         createPrefetchDataSet2();
 
-        SelectQuery<Painting> q = new SelectQuery<>(Painting.class);
-        q.addPrefetch(Painting.TO_ARTIST.disjoint());
-        q.addPrefetch(Painting.TO_ARTIST.dot(Artist.GROUP_ARRAY).disjoint());
-
-        List<Painting> objects = context.select(q);
+        List<Painting> objects = ObjectSelect.query(Painting.class)
+                .prefetch(Painting.TO_ARTIST.disjoint())
+                .prefetch(Painting.TO_ARTIST.dot(Artist.GROUP_ARRAY).disjoint())
+                .select(context);
 
         queryInterceptor.runWithQueriesBlocked(() -> assertPaintingResult(objects));
     }
@@ -139,10 +140,9 @@ public class FlattenedPrefetchIT extends ServerCase {
     public void testJointManyToMany() throws Exception {
         createPrefetchDataSet1();
 
-        SelectQuery<Artist> q = new SelectQuery<>(Artist.class);
-        q.addPrefetch(Artist.GROUP_ARRAY.joint());
-
-        List<Artist> objects = context.select(q);
+        List<Artist> objects = ObjectSelect.query(Artist.class)
+                .prefetch(Artist.GROUP_ARRAY.joint())
+                .select(context);
 
         queryInterceptor.runWithQueriesBlocked(() -> assertArtistResult(objects));
 
@@ -152,11 +152,10 @@ public class FlattenedPrefetchIT extends ServerCase {
     public void testJointMultiPrefetch() throws Exception {
         createPrefetchDataSet2();
 
-        SelectQuery<Painting> q = new SelectQuery<>(Painting.class);
-        q.addPrefetch(Painting.TO_ARTIST.joint());
-        q.addPrefetch(Painting.TO_ARTIST.dot(Artist.GROUP_ARRAY).joint());
-
-        List<Painting> objects = context.select(q);
+        List<Painting> objects = ObjectSelect.query(Painting.class)
+                .prefetch(Painting.TO_ARTIST.joint())
+                .prefetch(Painting.TO_ARTIST.dot(Artist.GROUP_ARRAY).joint())
+                .select(context);
 
         queryInterceptor.runWithQueriesBlocked(() -> assertPaintingResult(objects));
     }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/IdentityColumnsIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/IdentityColumnsIT.java
index 04a9631..1a71fe8 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/IdentityColumnsIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/IdentityColumnsIT.java
@@ -19,6 +19,8 @@
 
 package org.apache.cayenne.access;
 
+import java.util.List;
+
 import org.apache.cayenne.Cayenne;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.ObjectId;
@@ -27,7 +29,7 @@ import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.generated.GeneratedColumnCompKey;
@@ -43,8 +45,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.List;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -88,10 +88,10 @@ public class IdentityColumnsIT extends ServerCase {
 
         ObjectId id = idObject.getObjectId();
         context.invalidateObjects(idObject);
-
-        SelectQuery q = new SelectQuery(GeneratedColumnTestEntity.class);
-        q.setPageSize(10);
-        List<?> results = context.performQuery(q);
+        
+        List<?> results = ObjectSelect.query(GeneratedColumnTestEntity.class)
+                .pageSize(10)
+                .select(context);
         assertEquals(1, results.size());
 
         // per CAY-823 an attempt to resolve an object results in an exception
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/IncrementalFaultListIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/IncrementalFaultListIT.java
index 6102462..51822de 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/IncrementalFaultListIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/IncrementalFaultListIT.java
@@ -19,7 +19,7 @@
 package org.apache.cayenne.access;
 
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
 import org.apache.cayenne.unit.di.server.ServerCase;
@@ -38,12 +38,12 @@ public class IncrementalFaultListIT extends ServerCase {
 
     @Test
 	public void testSerialization() throws Exception {
-		SelectQuery query = new SelectQuery(Artist.class);
-		query.setPageSize(10);
-		
+		ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+				.pageSize(10);
+
 		IncrementalFaultList<Artist> i1 = new IncrementalFaultList<Artist>(context, query, 10);
 		IncrementalFaultList<Artist> i2 = Util.cloneViaSerialization(i1);
-		
+
 		assertNotNull(i2);
 		assertEquals(i1.getMaxFetchSize(), i2.getMaxFetchSize());
 		assertEquals(i1.getClass(), i2.getClass());
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/MiscTypesIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/MiscTypesIT.java
index 76e3390..731e209 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/MiscTypesIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/MiscTypesIT.java
@@ -18,10 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.lang.reflect.Array;
+
 import org.apache.cayenne.MockSerializable;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.testdo.misc_types.ArraysEntity;
 import org.apache.cayenne.testdo.misc_types.CharacterEntity;
 import org.apache.cayenne.testdo.misc_types.SerializableEntity;
@@ -31,8 +33,6 @@ import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Test;
 
-import java.lang.reflect.Array;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
@@ -42,13 +42,13 @@ public class MiscTypesIT extends ServerCase {
 
     @Inject
     private ObjectContext context;
-    
+
     @Inject
     private UnitDbAdapter accessStackAdapter;
-    
+
     @Test
     public void testSerializable() throws Exception {
-        
+
         // this test requires BLOB support
         if(!accessStackAdapter.supportsLobs()) {
             return;
@@ -61,8 +61,9 @@ public class MiscTypesIT extends ServerCase {
         test.setSerializableField(i);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(SerializableEntity.class);
-        SerializableEntity testRead = (SerializableEntity) context.performQuery(q).get(0);
+        SerializableEntity testRead = ObjectSelect
+                .query(SerializableEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getSerializableField());
         assertEquals(i.getName(), testRead.getSerializableField().getName());
 
@@ -80,8 +81,9 @@ public class MiscTypesIT extends ServerCase {
         test.setByteArray(a);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ArraysEntity.class);
-        ArraysEntity testRead = (ArraysEntity) context.performQuery(q).get(0);
+        ArraysEntity testRead = ObjectSelect
+                .query(ArraysEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getByteArray());
         assertArraysEqual(a, testRead.getByteArray());
 
@@ -99,8 +101,8 @@ public class MiscTypesIT extends ServerCase {
         test.setCharArray(a);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ArraysEntity.class);
-        ArraysEntity testRead = (ArraysEntity) context.performQuery(q).get(0);
+        ArraysEntity testRead = ObjectSelect.query(ArraysEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getCharArray());
         assertArraysEqual(a, testRead.getCharArray());
 
@@ -113,13 +115,13 @@ public class MiscTypesIT extends ServerCase {
         ArraysEntity test = context.newObject(ArraysEntity.class);
 
         Character[] a = new Character[] {
-                new Character('x'), new Character('y'), new Character('z')
+                'x', 'y', 'z'
         };
         test.setCharWrapperArray(a);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ArraysEntity.class);
-        ArraysEntity testRead = (ArraysEntity) context.performQuery(q).get(0);
+        ArraysEntity testRead = ObjectSelect.query(ArraysEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getCharWrapperArray());
         assertArraysEqual(a, testRead.getCharWrapperArray());
 
@@ -131,13 +133,14 @@ public class MiscTypesIT extends ServerCase {
     public void testCharacter() {
         CharacterEntity test = context.newObject(CharacterEntity.class);
 
-        test.setCharacterField(new Character('c'));
+        test.setCharacterField('c');
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(CharacterEntity.class);
-        CharacterEntity testRead = (CharacterEntity) context.performQuery(q).get(0);
+        CharacterEntity testRead = ObjectSelect
+                .query(CharacterEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getCharacterField());
-        assertEquals(new Character('c'), testRead.getCharacterField());
+        assertEquals((Character) 'c', testRead.getCharacterField());
 
         test.setCharacterField(null);
         context.commitChanges();
@@ -148,13 +151,14 @@ public class MiscTypesIT extends ServerCase {
         ArraysEntity test = context.newObject(ArraysEntity.class);
 
         Byte[] a = new Byte[] {
-                new Byte((byte) 1), new Byte((byte) 2), new Byte((byte) 3)
+                (byte) 1, (byte) 2, (byte) 3
         };
         test.setByteWrapperArray(a);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ArraysEntity.class);
-        ArraysEntity testRead = (ArraysEntity) context.performQuery(q).get(0);
+        ArraysEntity testRead = ObjectSelect
+                .query(ArraysEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getByteWrapperArray());
         assertArraysEqual(a, testRead.getByteWrapperArray());
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/NestedDataContextLocalCacheIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/NestedDataContextLocalCacheIT.java
index 1ad28fd..75aea68 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/NestedDataContextLocalCacheIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/NestedDataContextLocalCacheIT.java
@@ -18,20 +18,20 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.util.List;
+
 import org.apache.cayenne.BaseContext;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.QueryCacheStrategy;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
 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.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 
@@ -40,15 +40,15 @@ public class NestedDataContextLocalCacheIT extends ServerCase {
 
     @Inject
     protected ServerRuntime runtime;
-    
+
     @Inject
     private DataContext context;
 
     @Test
     public void testLocalCacheStaysLocal() {
 
-        SelectQuery query = new SelectQuery(Artist.class);
-        query.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                .cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
 
         ObjectContext child1 = runtime.newContext(context);
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/NestedDataContextWriteIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/NestedDataContextWriteIT.java
index 569eb77..dbca1ed 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/NestedDataContextWriteIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/NestedDataContextWriteIT.java
@@ -19,6 +19,11 @@
 
 package org.apache.cayenne.access;
 
+import java.sql.Types;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+
 import org.apache.cayenne.Cayenne;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.PersistenceState;
@@ -26,7 +31,7 @@ import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.testmap.ArtGroup;
@@ -40,11 +45,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.sql.Types;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-
 import static org.junit.Assert.*;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
@@ -52,7 +52,7 @@ public class NestedDataContextWriteIT extends ServerCase {
 
     @Inject
     private ServerRuntime runtime;
-    
+
     @Inject
     private DataContext context;
 
@@ -182,21 +182,21 @@ public class NestedDataContextWriteIT extends ServerCase {
         final ObjectContext childContext = runtime.newContext(context);
 
         // make sure we fetch in predictable order
-        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
-        query.addOrdering(Artist.ARTIST_NAME.asc());
-        List<?> objects = childContext.performQuery(query);
+        List<Artist> objects = ObjectSelect.query(Artist.class)
+                .orderBy(Artist.ARTIST_NAME.asc())
+                .select(childContext);
 
         assertEquals(4, objects.size());
 
         final Artist childNew = childContext.newObject(Artist.class);
         childNew.setArtistName("NNN");
 
-        final Artist childModified = (Artist) objects.get(0);
+        final Artist childModified = objects.get(0);
         childModified.setArtistName("MMM");
 
-        final Artist childCommitted = (Artist) objects.get(1);
+        final Artist childCommitted = objects.get(1);
 
-        final Artist childHollow = (Artist) objects.get(3);
+        final Artist childHollow = objects.get(3);
         childContext.invalidateObjects(childHollow);
 
         queryInterceptor.runWithQueriesBlocked(() -> {
@@ -254,14 +254,14 @@ public class NestedDataContextWriteIT extends ServerCase {
         ObjectContext childContext = runtime.newContext(context);
 
         // make sure we fetch in predictable order
-        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
-        query.addOrdering(Artist.ARTIST_NAME.asc());
-        List<?> objects = childContext.performQuery(query);
+        List<Artist> objects = ObjectSelect.query(Artist.class)
+                .orderBy(Artist.ARTIST_NAME.asc())
+                .select(childContext);
 
         assertEquals(4, objects.size());
 
         // delete AND modify
-        Artist childDeleted = (Artist) objects.get(2);
+        Artist childDeleted = objects.get(2);
         childContext.deleteObjects(childDeleted);
         childDeleted.setArtistName("DDD");
 
@@ -291,26 +291,26 @@ public class NestedDataContextWriteIT extends ServerCase {
         ObjectContext childContext = runtime.newContext(context);
 
         // make sure we fetch in predictable order
-        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
-        query.addOrdering(Artist.ARTIST_NAME.asc());
-        List<?> objects = childContext.performQuery(query);
+        List<Artist> objects = ObjectSelect.query(Artist.class)
+                .orderBy(Artist.ARTIST_NAME.asc())
+                .select(childContext);
 
         assertEquals(4, objects.size());
 
         Artist childNew = childContext.newObject(Artist.class);
         childNew.setArtistName("NNN");
 
-        Artist childModified = (Artist) objects.get(0);
+        Artist childModified = objects.get(0);
         childModified.setArtistName("MMM");
 
-        Artist childCommitted = (Artist) objects.get(1);
+        Artist childCommitted = objects.get(1);
 
         // delete AND modify
-        Artist childDeleted = (Artist) objects.get(2);
+        Artist childDeleted = objects.get(2);
         childContext.deleteObjects(childDeleted);
         childDeleted.setArtistName("DDD");
 
-        Artist childHollow = (Artist) objects.get(3);
+        Artist childHollow = objects.get(3);
         childContext.invalidateObjects(childHollow);
 
         childContext.commitChanges();
@@ -358,23 +358,23 @@ public class NestedDataContextWriteIT extends ServerCase {
         final ObjectContext childContext = runtime.newContext(context);
 
         // make sure we fetch in predictable order
-        SelectQuery<Painting> query = new SelectQuery<>(Painting.class);
-        query.addOrdering(Painting.PAINTING_TITLE.asc());
-        List<?> objects = childContext.performQuery(query);
+        List<Painting> objects = ObjectSelect.query(Painting.class)
+                .orderBy(Painting.PAINTING_TITLE.asc())
+                .select(childContext);
 
         assertEquals(6, objects.size());
 
-        final Painting childModifiedSimple = (Painting) objects.get(0);
+        final Painting childModifiedSimple = objects.get(0);
         childModifiedSimple.setPaintingTitle("C_PT");
 
-        final Painting childModifiedToOne = (Painting) objects.get(1);
+        final Painting childModifiedToOne = objects.get(1);
         childModifiedToOne.setToArtist(childModifiedSimple.getToArtist());
 
-        final Artist childModifiedToMany = ((Painting) objects.get(2)).getToArtist();
+        final Artist childModifiedToMany = objects.get(2).getToArtist();
 
         // ensure painting array is fully resolved...
         childModifiedToMany.getPaintingArray().size();
-        childModifiedToMany.addToPaintingArray((Painting) objects.get(3));
+        childModifiedToMany.addToPaintingArray(objects.get(3));
 
         queryInterceptor.runWithQueriesBlocked(() -> {
             Painting parentModifiedSimple;
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/NumericTypesIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/NumericTypesIT.java
index a8507f5..7189dfb 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/NumericTypesIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/NumericTypesIT.java
@@ -19,15 +19,17 @@
 
 package org.apache.cayenne.access;
 
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.List;
+
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.exp.property.NumericProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.query.ObjectSelect;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.numeric_types.BigDecimalEntity;
@@ -45,10 +47,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.List;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
@@ -102,8 +100,8 @@ public class NumericTypesIT extends ServerCase {
         test.setLongField(i);
         context.commitChanges();
 
-        SelectQuery<LongEntity> q = new SelectQuery<>(LongEntity.class);
-        LongEntity testRead = (LongEntity) context.performQuery(q).get(0);
+        LongEntity testRead = ObjectSelect.query(LongEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getLongField());
         assertEquals(i, testRead.getLongField());
 
@@ -120,8 +118,8 @@ public class NumericTypesIT extends ServerCase {
         test.setBigIntegerField(i);
         context.commitChanges();
 
-        SelectQuery<BigIntegerEntity> q = new SelectQuery<>(BigIntegerEntity.class);
-        BigIntegerEntity testRead = (BigIntegerEntity) context.performQuery(q).get(0);
+        BigIntegerEntity testRead = ObjectSelect.query(BigIntegerEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getBigIntegerField());
         assertEquals(i, testRead.getBigIntegerField());
 
@@ -138,8 +136,8 @@ public class NumericTypesIT extends ServerCase {
         test.setBigDecimalField(i);
         context.commitChanges();
 
-        SelectQuery<BigDecimalEntity> q = new SelectQuery<>(BigDecimalEntity.class);
-        BigDecimalEntity testRead = (BigDecimalEntity) context.performQuery(q).get(0);
+        BigDecimalEntity testRead = ObjectSelect.query(BigDecimalEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getBigDecimalField());
         assertEquals(i, testRead.getBigDecimalField());
 
@@ -152,21 +150,20 @@ public class NumericTypesIT extends ServerCase {
         createShortDataSet();
 
         // test
-        Expression qual = ExpressionFactory.matchExp("smallintCol", new Short("9999"));
-        List<?> objects = context.performQuery(new SelectQuery<>(
-                SmallintTestEntity.class,
-                qual));
+        List<SmallintTestEntity> objects = ObjectSelect.query(SmallintTestEntity.class)
+                .where(SmallintTestEntity.SMALLINT_COL.eq(Short.valueOf("9999")))
+                .select(context);
         assertEquals(1, objects.size());
 
-        SmallintTestEntity object = (SmallintTestEntity) objects.get(0);
-        assertEquals(new Short("9999"), object.getSmallintCol());
+        SmallintTestEntity object = objects.get(0);
+        assertEquals(Short.valueOf("9999"), object.getSmallintCol());
     }
 
     @Test
     public void testShortInInsert() throws Exception {
         SmallintTestEntity object = (SmallintTestEntity) (context)
                 .newObject("SmallintTestEntity");
-        object.setSmallintCol(new Short("1"));
+        object.setSmallintCol(Short.valueOf("1"));
         context.commitChanges();
     }
 
@@ -175,14 +172,13 @@ public class NumericTypesIT extends ServerCase {
         createTinyintDataSet();
 
         // test
-        Expression qual = ExpressionFactory.matchExp("tinyintCol", (byte) 81);
-        List<?> objects = context.performQuery(new SelectQuery<>(
-                TinyintTestEntity.class,
-                qual));
+        List<?> objects = ObjectSelect.query(TinyintTestEntity.class)
+                .where(TinyintTestEntity.TINYINT_COL.eq((byte) 81))
+                .select(context);
         assertEquals(1, objects.size());
 
         TinyintTestEntity object = (TinyintTestEntity) objects.get(0);
-        assertEquals(new Byte((byte) 81), object.getTinyintCol());
+        assertEquals(Byte.valueOf((byte) 81), object.getTinyintCol());
     }
 
     @Test
@@ -204,10 +200,9 @@ public class NumericTypesIT extends ServerCase {
         context.invalidateObjects(trueObject, falseObject);
 
         // fetch true...
-        Expression trueQ = ExpressionFactory.matchExp("bitColumn", Boolean.TRUE);
-        List<?> trueResult = context1.performQuery(new SelectQuery<>(
-                BitTestEntity.class,
-                trueQ));
+        List<?> trueResult = ObjectSelect.query(BitTestEntity.class)
+                .where(BitTestEntity.BIT_COLUMN.eq(Boolean.TRUE))
+                .select(context1);
         assertEquals(1, trueResult.size());
 
         BitTestEntity trueRefetched = (BitTestEntity) trueResult.get(0);
@@ -218,10 +213,9 @@ public class NumericTypesIT extends ServerCase {
         assertSame(Boolean.TRUE, trueRefetched.getBitColumn());
 
         // fetch false
-        Expression falseQ = ExpressionFactory.matchExp("bitColumn", Boolean.FALSE);
-        List<?> falseResult = context1.performQuery(new SelectQuery<>(
-                BitTestEntity.class,
-                falseQ));
+        List<?> falseResult = ObjectSelect.query(BitTestEntity.class)
+                .where(BitTestEntity.BIT_COLUMN.eq(Boolean.FALSE))
+                .select(context1);
         assertEquals(1, falseResult.size());
 
         BitTestEntity falseRefetched = (BitTestEntity) falseResult.get(0);
@@ -247,10 +241,9 @@ public class NumericTypesIT extends ServerCase {
         context.invalidateObjects(trueObject, falseObject);
 
         // fetch true...
-        Expression trueQ = ExpressionFactory.matchExp("booleanColumn", Boolean.TRUE);
-        List<?> trueResult = context1.performQuery(new SelectQuery<>(
-                BooleanTestEntity.class,
-                trueQ));
+        List<?> trueResult = ObjectSelect.query(BooleanTestEntity.class)
+                .where(BooleanTestEntity.BOOLEAN_COLUMN.eq(Boolean.TRUE))
+                .select(context1);
         assertEquals(1, trueResult.size());
 
         BooleanTestEntity trueRefetched = (BooleanTestEntity) trueResult.get(0);
@@ -261,10 +254,9 @@ public class NumericTypesIT extends ServerCase {
         assertSame(Boolean.TRUE, trueRefetched.getBooleanColumn());
 
         // fetch false
-        Expression falseQ = ExpressionFactory.matchExp("booleanColumn", Boolean.FALSE);
-        List<?> falseResult = context1.performQuery(new SelectQuery<>(
-                BooleanTestEntity.class,
-                falseQ));
+        List<?> falseResult = ObjectSelect.query(BooleanTestEntity.class)
+                .where(BooleanTestEntity.BOOLEAN_COLUMN.eq(Boolean.FALSE))
+                .select(context1);
         assertEquals(1, falseResult.size());
 
         BooleanTestEntity falseRefetched = (BooleanTestEntity) falseResult.get(0);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/OptimisticLockingIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/OptimisticLockingIT.java
index 47438c4..19ce8a0 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/OptimisticLockingIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/OptimisticLockingIT.java
@@ -19,10 +19,13 @@
 
 package org.apache.cayenne.access;
 
+import java.sql.Types;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.Ordering;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.query.SortOrder;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
@@ -34,10 +37,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.sql.Types;
-import java.util.List;
-import java.util.Map;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -114,8 +113,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testSuccessSimpleLockingOnDelete() throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -132,8 +132,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testSuccessSimpleLockingOnDeleteFollowedByInvalidate() throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -152,8 +153,9 @@ public class OptimisticLockingIT extends ServerCase {
             throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -171,8 +173,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testSuccessSimpleLockingOnDeletePrecededByInvalidate() throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -191,8 +194,9 @@ public class OptimisticLockingIT extends ServerCase {
             throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -210,8 +214,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testFailSimpleLockingOnDelete() throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -238,8 +243,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testSuccessSimpleLockingOnUpdate() throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -278,8 +284,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testSuccessSimpleLockingOnUpdateFollowedByInvalidate() throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -298,8 +305,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testSuccessSimpleLockingOnUpdatePrecededByInvalidate() throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -319,8 +327,9 @@ public class OptimisticLockingIT extends ServerCase {
             throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -340,8 +349,9 @@ public class OptimisticLockingIT extends ServerCase {
             throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -360,8 +370,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testFailSimpleLocking() throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -389,8 +400,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testFailLockingOnNull() throws Exception {
         createLockingOnNullDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -419,15 +431,14 @@ public class OptimisticLockingIT extends ServerCase {
     public void testSuccessLockingOnMixed() throws Exception {
         createLockingOnMixedDataSet();
 
-        SelectQuery<SimpleLockingTestEntity> query = new SelectQuery<>(SimpleLockingTestEntity.class);
-        query.addOrdering(new Ordering("db:LOCKING_TEST_ID", SortOrder.ASCENDING));
-
-        List<?> allObjects = context.performQuery(query);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect.query(SimpleLockingTestEntity.class)
+                .orderBy(new Ordering("db:LOCKING_TEST_ID", SortOrder.ASCENDING))
+                .select(context);
         assertEquals(3, allObjects.size());
 
-        SimpleLockingTestEntity object1 = (SimpleLockingTestEntity) allObjects.get(0);
-        SimpleLockingTestEntity object2 = (SimpleLockingTestEntity) allObjects.get(1);
-        SimpleLockingTestEntity object3 = (SimpleLockingTestEntity) allObjects.get(2);
+        SimpleLockingTestEntity object1 = allObjects.get(0);
+        SimpleLockingTestEntity object2 = allObjects.get(1);
+        SimpleLockingTestEntity object3 = allObjects.get(2);
 
         // change description and save... no optimistic lock failure expected...
         object1.setDescription("first update for object1");
@@ -444,8 +455,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testSuccessLockingOnToOneNull() throws Exception {
         createLockingOnToOneDataSet();
 
-        List<RelLockingTestEntity> allObjects = new SelectQuery<>(
-                RelLockingTestEntity.class).select(context);
+        List<RelLockingTestEntity> allObjects = ObjectSelect
+                .query(RelLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         RelLockingTestEntity object = allObjects.get(0);
@@ -459,13 +471,14 @@ public class OptimisticLockingIT extends ServerCase {
         object.setToSimpleLockingTest(object1);
         context.commitChanges();
     }
-    
+
     @Test
     public void testFailLockingOnToOne() throws Exception {
         createLockingOnToOneDataSet();
 
-        List<RelLockingTestEntity> allObjects = new SelectQuery<>(
-                RelLockingTestEntity.class).select(context);
+        List<RelLockingTestEntity> allObjects = ObjectSelect
+                .query(RelLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         RelLockingTestEntity object = allObjects.get(0);
@@ -499,8 +512,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testFailRetrieveRow() throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
@@ -525,8 +539,9 @@ public class OptimisticLockingIT extends ServerCase {
     public void testFailRetrieveDeletedRow() throws Exception {
         createSimpleLockingDataSet();
 
-        List<SimpleLockingTestEntity> allObjects = new SelectQuery<>(
-                SimpleLockingTestEntity.class).select(context);
+        List<SimpleLockingTestEntity> allObjects = ObjectSelect
+                .query(SimpleLockingTestEntity.class)
+                .select(context);
         assertEquals(1, allObjects.size());
 
         SimpleLockingTestEntity object = allObjects.get(0);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/ReturnTypesMappingIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/ReturnTypesMappingIT.java
index c3ce084..1ea2724 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/ReturnTypesMappingIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/ReturnTypesMappingIT.java
@@ -18,10 +18,16 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.math.BigDecimal;
+import java.sql.Time;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.query.MappedSelect;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.testdo.return_types.ReturnTypesMap1;
 import org.apache.cayenne.testdo.return_types.ReturnTypesMap2;
 import org.apache.cayenne.testdo.return_types.ReturnTypesMapLobs1;
@@ -32,13 +38,10 @@ import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Test;
 
-import java.math.BigDecimal;
-import java.sql.Time;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Date;
-
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 /**
@@ -49,12 +52,12 @@ public class ReturnTypesMappingIT extends ServerCase {
 
     @Inject
     private DataContext context;
-    
+
     @Inject
     private UnitDbAdapter unitDbAdapter;
 
     /*
-     * TODO: olga: We need divided TYPES_MAPPING_TES2 to 2 schemas with lobs columns and not lobs columns 
+     * TODO: olga: We need divided TYPES_MAPPING_TES2 to 2 schemas with lobs columns and not lobs columns
      */
 
     @Test
@@ -65,7 +68,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         Long bigintValue = 5326457654783454355l;
         test.setBigintColumn(bigintValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -81,13 +84,14 @@ public class ReturnTypesMappingIT extends ServerCase {
     @Test
     public void testBIGINT2() throws Exception {
        ReturnTypesMap1 test = context.newObject(ReturnTypesMap1.class);
-    
+
         Long bigintValue = 5326457654783454355l;
         test.setBigintColumn(bigintValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         Long columnValue = testRead.getBigintColumn();
         assertNotNull(columnValue);
         assertEquals(Long.class, columnValue.getClass());
@@ -99,13 +103,13 @@ public class ReturnTypesMappingIT extends ServerCase {
         if (unitDbAdapter.supportsLobs()) {
             String columnName = "BINARY_COLUMN";
             ReturnTypesMap2 test = context.newObject(ReturnTypesMap2.class);
-    
+
             byte[] binaryValue = {
                     3, 4, 5, -6, 7, 0, 2, 9, 45, 64, 3, 127, -128, -60
             };
             test.setBinaryColumn(binaryValue);
             context.commitChanges();
-			
+
             DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap2")).get(0);
             Object columnValue = testRead.get(columnName);
             assertNotNull(columnValue);
@@ -118,19 +122,20 @@ public class ReturnTypesMappingIT extends ServerCase {
     public void testBINARY2() throws Exception {
         if (unitDbAdapter.supportsLobs()) {
             ReturnTypesMap2 test = context.newObject(ReturnTypesMap2.class);
-    
+
             byte[] binaryValue = {
                     3, 4, 5, -6, 7, 0, 2, 9, 45, 64, 3, 127, -128, -60
             };
             test.setBinaryColumn(binaryValue);
             context.commitChanges();
-    
-            SelectQuery q = new SelectQuery(ReturnTypesMap2.class);
-            ReturnTypesMap2 testRead = (ReturnTypesMap2) context.performQuery(q).get(0);
+
+            ReturnTypesMap2 testRead = ObjectSelect
+                    .query(ReturnTypesMap2.class)
+                    .selectFirst(context);
             byte[] columnValue = testRead.getBinaryColumn();
             assertNotNull(columnValue);
             assertEquals(byte[].class, columnValue.getClass());
-            assertTrue(Arrays.equals(binaryValue, columnValue));
+            assertArrayEquals(binaryValue, columnValue);
         }
     }
 
@@ -142,7 +147,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         Boolean bitValue = true;
         test.setBitColumn(bitValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -160,8 +165,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setBitColumn(bitValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         Boolean columnValue = testRead.getBitColumn();
         assertNotNull(columnValue);
         assertEquals(Boolean.class, columnValue.getClass());
@@ -176,13 +182,13 @@ public class ReturnTypesMappingIT extends ServerCase {
         if (unitDbAdapter.supportsLobs()) {
             String columnName = "BLOB_COLUMN";
             ReturnTypesMap2 test = context.newObject(ReturnTypesMap2.class);
-    
+
             byte[] blobValue = {
                     3, 4, 5, -6, 7, 0, 2, 9, 45, 64, 3, 127, -128, -60
             };
             test.setBlobColumn(blobValue);
             context.commitChanges();
-			
+
             DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap2")).get(0);
             Object columnValue = testRead.get(columnName);
             assertNotNull(columnValue);
@@ -195,15 +201,16 @@ public class ReturnTypesMappingIT extends ServerCase {
     public void testBLOB2() throws Exception {
         if (unitDbAdapter.supportsLobs()) {
             ReturnTypesMap2 test = context.newObject(ReturnTypesMap2.class);
-    
+
             byte[] blobValue = {
                     3, 4, 5, -6, 7, 0, 2, 9, 45, 64, 3, 127, -128, -60
             };
             test.setBlobColumn(blobValue);
             context.commitChanges();
-    
-            SelectQuery q = new SelectQuery(ReturnTypesMap2.class);
-            ReturnTypesMap2 testRead = (ReturnTypesMap2) context.performQuery(q).get(0);
+
+            ReturnTypesMap2 testRead = ObjectSelect
+                    .query(ReturnTypesMap2.class)
+                    .selectFirst(context);
             byte[] columnValue = testRead.getBlobColumn();
             assertNotNull(columnValue);
             assertEquals(byte[].class, columnValue.getClass());
@@ -219,7 +226,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         Boolean booleanValue = true;
         test.setBooleanColumn(booleanValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -238,8 +245,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setBooleanColumn(booleanValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         Boolean columnValue = testRead.getBooleanColumn();
         assertNotNull(columnValue);
         assertEquals(Boolean.class, columnValue.getClass());
@@ -254,7 +262,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         String charValue = "Char string for tests!";
         test.setCharColumn(charValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -270,7 +278,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         String charValue = "درخت‌های جستجوی متوازن، نیازی ندارد که به صورت!";
         test.setNcharColumn(charValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -286,8 +294,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setCharColumn(charValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         String columnValue = testRead.getCharColumn();
         assertNotNull(columnValue);
         assertEquals(String.class, columnValue.getClass());
@@ -299,7 +308,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         if (unitDbAdapter.supportsLobs()) {
             String columnName = "CLOB_COLUMN";
             ReturnTypesMapLobs1 test = context.newObject(ReturnTypesMapLobs1.class);
-    
+
             StringBuffer buffer = new StringBuffer();
             for (int i = 0; i < 10000; i++) {
                 buffer.append("CLOB very large string for tests!!!!\n");
@@ -307,7 +316,7 @@ public class ReturnTypesMappingIT extends ServerCase {
             String clobValue = buffer.toString();
             test.setClobColumn(clobValue);
             context.commitChanges();
-			
+
             DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesLobsMap1")).get(0);
             Object columnValue = testRead.get(columnName);
             if (columnValue == null && testRead.containsKey(columnName.toLowerCase())) {
@@ -333,7 +342,7 @@ public class ReturnTypesMappingIT extends ServerCase {
             String clobValue = buffer.toString();
             test.setNclobColumn(clobValue);
             context.commitChanges();
-			
+
             DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesLobsMap1")).get(0);
             Object columnValue = testRead.get(columnName);
             if (columnValue == null && testRead.containsKey(columnName.toLowerCase())) {
@@ -349,7 +358,7 @@ public class ReturnTypesMappingIT extends ServerCase {
     public void testCLOB2() throws Exception {
         if (unitDbAdapter.supportsLobs()) {
             ReturnTypesMapLobs1 test = context.newObject(ReturnTypesMapLobs1.class);
-    
+
             StringBuffer buffer = new StringBuffer();
             for (int i = 0; i < 10000; i++) {
                 buffer.append("CLOB very large string for tests!!!!\n");
@@ -357,9 +366,10 @@ public class ReturnTypesMappingIT extends ServerCase {
             String clobValue = buffer.toString();
             test.setClobColumn(clobValue);
             context.commitChanges();
-    
-            SelectQuery q = new SelectQuery(ReturnTypesMapLobs1.class);
-            ReturnTypesMapLobs1 testRead = (ReturnTypesMapLobs1) context.performQuery(q).get(0);
+
+            ReturnTypesMapLobs1 testRead = ObjectSelect
+                    .query(ReturnTypesMapLobs1.class)
+                    .selectFirst(context);
             String columnValue = testRead.getClobColumn();
             assertNotNull(columnValue);
             assertEquals(String.class, columnValue.getClass());
@@ -378,7 +388,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         Date dateValue = cal.getTime();
         test.setDateColumn(dateValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -397,8 +407,10 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setDateColumn(dateValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         Date columnValue = testRead.getDateColumn();
         assertNotNull(columnValue);
         assertEquals(Date.class, columnValue.getClass());
@@ -413,7 +425,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         BigDecimal decimalValue = new BigDecimal("578438.57843");
         test.setDecimalColumn(decimalValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -429,8 +441,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setDecimalColumn(decimalValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         BigDecimal columnValue = testRead.getDecimalColumn();
         assertNotNull(columnValue);
         assertEquals(BigDecimal.class, columnValue.getClass());
@@ -445,7 +458,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         Double doubleValue = 3298.4349783d;
         test.setDoubleColumn(doubleValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -466,8 +479,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setDoubleColumn(doubleValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         Double columnValue = testRead.getDoubleColumn();
         assertNotNull(columnValue);
         assertEquals(Double.class, columnValue.getClass());
@@ -482,7 +496,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         Float floatValue = 375.437f;
         test.setFloatColumn(floatValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -503,8 +517,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setFloatColumn(floatValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         Float columnValue = testRead.getFloatColumn();
         assertNotNull(columnValue);
         assertEquals(Float.class, columnValue.getClass());
@@ -519,7 +534,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         Integer integerValue = 54235;
         test.setIntegerColumn(integerValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -535,8 +550,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setIntegerColumn(integerValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         Integer columnValue = testRead.getIntegerColumn();
         assertNotNull(columnValue);
         assertEquals(Integer.class, columnValue.getClass());
@@ -548,13 +564,13 @@ public class ReturnTypesMappingIT extends ServerCase {
         if (unitDbAdapter.supportsLobs()) {
             String columnName = "LONGVARBINARY_COLUMN";
             ReturnTypesMap2 test = context.newObject(ReturnTypesMap2.class);
-    
+
             byte[] longvarbinaryValue = {
                     3, 4, 5, -6, 7, 0, 2, 9, 45, 64, 3, 127, -128, -60
             };
             test.setLongvarbinaryColumn(longvarbinaryValue);
             context.commitChanges();
-			
+
             DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap2")).get(0);
             Object columnValue = testRead.get(columnName);
             assertNotNull(columnValue);
@@ -567,15 +583,16 @@ public class ReturnTypesMappingIT extends ServerCase {
     public void testLONGVARBINARY2() throws Exception {
         if (unitDbAdapter.supportsLobs()) {
             ReturnTypesMap2 test = context.newObject(ReturnTypesMap2.class);
-    
+
             byte[] longvarbinaryValue = {
                     3, 4, 5, -6, 7, 0, 2, 9, 45, 64, 3, 127, -128, -60
             };
             test.setLongvarbinaryColumn(longvarbinaryValue);
             context.commitChanges();
-    
-            SelectQuery q = new SelectQuery(ReturnTypesMap2.class);
-            ReturnTypesMap2 testRead = (ReturnTypesMap2) context.performQuery(q).get(0);
+
+            ReturnTypesMap2 testRead = ObjectSelect
+                    .query(ReturnTypesMap2.class)
+                    .selectFirst(context);
             byte[] columnValue = testRead.getLongvarbinaryColumn();
             assertNotNull(columnValue);
             assertEquals(byte[].class, columnValue.getClass());
@@ -595,7 +612,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         String longvarcharValue = buffer.toString();
         test.setLongvarcharColumn(longvarcharValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -615,7 +632,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         String longnvarcharValue = buffer.toString();
         test.setLongnvarcharColumn(longnvarcharValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -635,8 +652,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setLongvarcharColumn(longvarcharValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         String columnValue = testRead.getLongvarcharColumn();
         assertNotNull(columnValue);
         assertEquals(String.class, columnValue.getClass());
@@ -651,7 +669,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         BigDecimal numericValue = new BigDecimal("578438.57843");
         test.setNumericColumn(numericValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -667,8 +685,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setNumericColumn(numericValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         BigDecimal columnValue = testRead.getNumericColumn();
         assertNotNull(columnValue);
         assertEquals(BigDecimal.class, columnValue.getClass());
@@ -683,7 +702,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         Float realValue = 5788.57843f;
         test.setRealColumn(realValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -711,8 +730,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setRealColumn(realValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         Float columnValue = testRead.getRealColumn();
         assertNotNull(columnValue);
         assertEquals(Float.class, columnValue.getClass());
@@ -728,7 +748,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         Integer intValue = 32564;
         test.setSmallintColumn(smallintValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -749,8 +769,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setSmallintColumn(smallintValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         Short columnValue = testRead.getSmallintColumn();
         assertNotNull(columnValue);
         assertEquals(Short.class, columnValue.getClass());
@@ -768,7 +789,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         Date timeValue = new Time(cal.getTime().getTime());
         test.setTimeColumn(timeValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -788,8 +809,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setTimeColumn(timeValue);
         context.commitChanges();
 
-        SelectQuery<ReturnTypesMap1> q = new SelectQuery<>(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = q.selectOne(context);
+        ReturnTypesMap1 testRead =ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectOne(context);
         Date columnValue = testRead.getTimeColumn();
         assertNotNull(columnValue);
         assertEquals(Date.class, columnValue.getClass());
@@ -804,12 +826,12 @@ public class ReturnTypesMappingIT extends ServerCase {
         Date timestampValue = Calendar.getInstance().getTime();
         test.setTimestampColumn(timestampValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
         assertEquals(Date.class, columnValue.getClass());
-        
+
         // some DB's, noteably MySQL, strip the milliseconds from timestamps,
         // so comparing within 1 second precision
         long delta = timestampValue.getTime() - ((Date) columnValue).getTime();
@@ -824,12 +846,13 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setTimestampColumn(timestampValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         Date columnValue = testRead.getTimestampColumn();
         assertNotNull(columnValue);
         assertEquals(Date.class, columnValue.getClass());
-        
+
         // some DB's, noteably MySQL, strip the milliseconds from timestamps,
         // so comparing within 1 second precision
         long delta = timestampValue.getTime() - ((Date) columnValue).getTime();
@@ -844,7 +867,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         Integer intValue = 89;
         test.setTinyintColumn(tinyintValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -864,8 +887,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setTinyintColumn(tinyintValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         Byte columnValue = testRead.getTinyintColumn();
         assertNotNull(columnValue);
         assertEquals(Byte.class, columnValue.getClass());
@@ -877,13 +901,13 @@ public class ReturnTypesMappingIT extends ServerCase {
         if (unitDbAdapter.supportsLobs()) {
             String columnName = "VARBINARY_COLUMN";
             ReturnTypesMap2 test = context.newObject(ReturnTypesMap2.class);
-    
+
             byte[] varbinaryValue = {
                     3, 4, 5, -6, 7, 0, 2, 9, 45, 64, 3, 127, -128, -60
             };
             test.setVarbinaryColumn(varbinaryValue);
             context.commitChanges();
-			
+
             DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap2")).get(0);
             Object columnValue = testRead.get(columnName);
             assertNotNull(columnValue);
@@ -896,15 +920,16 @@ public class ReturnTypesMappingIT extends ServerCase {
     public void testVARBINARY2() throws Exception {
         if (unitDbAdapter.supportsLobs()) {
             ReturnTypesMap2 test = context.newObject(ReturnTypesMap2.class);
-    
+
             byte[] varbinaryValue = {
                     3, 4, 5, -6, 7, 0, 2, 9, 45, 64, 3, 127, -128, -60
             };
             test.setVarbinaryColumn(varbinaryValue);
             context.commitChanges();
-    
-            SelectQuery q = new SelectQuery(ReturnTypesMap2.class);
-            ReturnTypesMap2 testRead = (ReturnTypesMap2) context.performQuery(q).get(0);
+
+            ReturnTypesMap2 testRead = ObjectSelect
+                    .query(ReturnTypesMap2.class)
+                    .selectFirst(context);
             byte[] columnValue = testRead.getVarbinaryColumn();
             assertNotNull(columnValue);
             assertEquals(byte[].class, columnValue.getClass());
@@ -920,7 +945,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         String varcharValue = "VARChar string for tests!";
         test.setVarcharColumn(varcharValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -936,7 +961,7 @@ public class ReturnTypesMappingIT extends ServerCase {
         String varcharValue = "ی متوازن، نیازی ندارد که ب";
         test.setNvarcharColumn(varcharValue);
         context.commitChanges();
-		
+
         DataRow testRead = (DataRow) context.performQuery(MappedSelect.query("SelectReturnTypesMap1")).get(0);
         Object columnValue = testRead.get(columnName);
         assertNotNull(columnValue);
@@ -952,8 +977,9 @@ public class ReturnTypesMappingIT extends ServerCase {
         test.setVarcharColumn(varcharValue);
         context.commitChanges();
 
-        SelectQuery q = new SelectQuery(ReturnTypesMap1.class);
-        ReturnTypesMap1 testRead = (ReturnTypesMap1) context.performQuery(q).get(0);
+        ReturnTypesMap1 testRead = ObjectSelect
+                .query(ReturnTypesMap1.class)
+                .selectFirst(context);
         String columnValue = testRead.getVarcharColumn();
         assertNotNull(columnValue);
         assertEquals(String.class, columnValue.getClass());
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/SimpleIdIncrementalFaultListIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/SimpleIdIncrementalFaultListIT.java
index bda55e8..9727128 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/SimpleIdIncrementalFaultListIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/SimpleIdIncrementalFaultListIT.java
@@ -19,11 +19,13 @@
 
 package org.apache.cayenne.access;
 
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
 import org.apache.cayenne.DataObject;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.SortOrder;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
@@ -34,10 +36,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-
 import static org.junit.Assert.*;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
@@ -91,8 +89,8 @@ public class SimpleIdIncrementalFaultListIT extends ServerCase {
 
         // DataContext context = createDataContext();
 
-        SelectQuery query = new SelectQuery(Artist.class);
-        query.setPageSize(10);
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                .pageSize(10);
         SimpleIdIncrementalFaultList<Artist> list = new SimpleIdIncrementalFaultList<Artist>(
                 context,
                 query, 10000);
@@ -110,13 +108,12 @@ public class SimpleIdIncrementalFaultListIT extends ServerCase {
     private SimpleIdIncrementalFaultList<?> prepareList(int pageSize) throws Exception {
         createArtistsDataSet();
 
-        SelectQuery query = new SelectQuery(Artist.class);
-
-        // make sure total number of objects is not divisable
-        // by the page size, to test the last smaller page
-        query.setPageSize(pageSize);
-        query.addOrdering("db:ARTIST_ID", SortOrder.ASCENDING);
-        return new SimpleIdIncrementalFaultList<Object>(context, query, 10000);
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                // make sure total number of objects is not divisable
+                // by the page size, to test the last smaller page
+                .pageSize(pageSize)
+                .orderBy("db:ARTIST_ID", SortOrder.ASCENDING);
+        return new SimpleIdIncrementalFaultList<>(context, query, 10000);
     }
 
     @Test
@@ -170,11 +167,11 @@ public class SimpleIdIncrementalFaultListIT extends ServerCase {
         newArtist.setArtistName("x");
         context.commitChanges();
 
-        SelectQuery<Artist> q = new SelectQuery<Artist>(Artist.class);
-        q.setPageSize(6);
-        q.addOrdering(Artist.ARTIST_NAME.asc());
+        ObjectSelect<Artist> q = ObjectSelect.query(Artist.class)
+                .pageSize(6)
+                .orderBy(Artist.ARTIST_NAME.asc());
 
-        SimpleIdIncrementalFaultList<?> list = new SimpleIdIncrementalFaultList<Object>(
+        SimpleIdIncrementalFaultList<Artist> list = new SimpleIdIncrementalFaultList<>(
                 context,
                 q, 10000);
 
@@ -277,9 +274,9 @@ public class SimpleIdIncrementalFaultListIT extends ServerCase {
     @Test
     public void testIndexOf() throws Exception {
         SimpleIdIncrementalFaultList<?> list = prepareList(6);
-        Expression qual = ExpressionFactory.matchExp("artistName", "artist20");
-        SelectQuery query = new SelectQuery(Artist.class, qual);
-        List<?> artists = list.dataContext.performQuery(query);
+        List<?> artists = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.eq("artist20"))
+                .select(list.dataContext);
 
         assertEquals(1, artists.size());
 
@@ -291,9 +288,9 @@ public class SimpleIdIncrementalFaultListIT extends ServerCase {
     @Test
     public void testLastIndexOf() throws Exception {
         SimpleIdIncrementalFaultList<?> list = prepareList(6);
-        Expression qual = ExpressionFactory.matchExp("artistName", "artist20");
-        SelectQuery query = new SelectQuery(Artist.class, qual);
-        List<?> artists = list.dataContext.performQuery(query);
+        List<?> artists = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.eq("artist20"))
+                .select(list.dataContext);
 
         assertEquals(1, artists.size());
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/SimpleIdIncrementalFaultListPrefetchIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/SimpleIdIncrementalFaultListPrefetchIT.java
index 71abdf4..faeb0eb 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/SimpleIdIncrementalFaultListPrefetchIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/SimpleIdIncrementalFaultListPrefetchIT.java
@@ -19,28 +19,26 @@
 
 package org.apache.cayenne.access;
 
+import java.util.List;
+
 import org.apache.cayenne.DataObject;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.PersistenceState;
 import org.apache.cayenne.ValueHolder;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.PrefetchTreeNode;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.testdo.testmap.Painting;
 import org.apache.cayenne.unit.di.DataChannelInterceptor;
-import org.apache.cayenne.unit.di.UnitTestClosure;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
 import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.List;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -98,14 +96,12 @@ public class SimpleIdIncrementalFaultListPrefetchIT extends ServerCase {
 
     @Test
     public void testListType() throws Exception {
-
         createArtistsDataSet();
 
-        Expression e = Artist.ARTIST_NAME.like("artist1%");
-        SelectQuery q = new SelectQuery("Artist", e);
-        q.setPageSize(4);
-
-        List<?> result = context.performQuery(q);
+        List<?> result = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.like("artist1%"))
+                .pageSize(4)
+                .select(context);
         assertTrue(result instanceof SimpleIdIncrementalFaultList);
     }
 
@@ -115,13 +111,12 @@ public class SimpleIdIncrementalFaultListPrefetchIT extends ServerCase {
      */
     @Test
     public void testPrefetch1() throws Exception {
-
         createArtistsAndPaintingsDataSet();
 
-        Expression e = ExpressionFactory.likeExp("artistName", "artist1%");
-        SelectQuery q = new SelectQuery("Artist", e);
-        q.addPrefetch("paintingArray");
-        q.setPageSize(3);
+        ObjectSelect<Artist> q = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.like("artist1%"))
+                .prefetch("paintingArray", PrefetchTreeNode.UNDEFINED_SEMANTICS)
+                .pageSize(3);
 
         final IncrementalFaultList<?> result = (IncrementalFaultList) context
                 .performQuery(q);
@@ -131,13 +126,10 @@ public class SimpleIdIncrementalFaultListPrefetchIT extends ServerCase {
         // currently queries with prefetch do not resolve their first page
         assertEquals(result.size(), result.getUnfetchedObjects());
 
-        int count = queryInterceptor.runWithQueryCounter(new UnitTestClosure() {
-
-            public void execute() {
-                // go through the second page objects and count queries
-                for (int i = 3; i < 6; i++) {
-                    result.get(i);
-                }
+        int count = queryInterceptor.runWithQueryCounter(() -> {
+            // go through the second page objects and count queries
+            for (int i = 3; i < 6; i++) {
+                result.get(i);
             }
         });
 
@@ -150,13 +142,12 @@ public class SimpleIdIncrementalFaultListPrefetchIT extends ServerCase {
      */
     @Test
     public void testPrefetch3() throws Exception {
-
         createArtistsAndPaintingsDataSet();
 
-        Expression e = ExpressionFactory.likeExp("artistName", "artist1%");
-        SelectQuery q = new SelectQuery("Artist", e);
-        q.addPrefetch("paintingArray");
-        q.setPageSize(3);
+        ObjectSelect<Artist> q = ObjectSelect.query(Artist.class)
+                .where(Artist.ARTIST_NAME.like("artist1%"))
+                .prefetch("paintingArray", PrefetchTreeNode.UNDEFINED_SEMANTICS)
+                .pageSize(3);
 
         IncrementalFaultList result = (IncrementalFaultList) context.performQuery(q);
 
@@ -180,30 +171,26 @@ public class SimpleIdIncrementalFaultListPrefetchIT extends ServerCase {
      */
     @Test
     public void testPrefetch4() throws Exception {
-
         createArtistsAndPaintingsDataSet();
 
-        SelectQuery q = new SelectQuery(Painting.class);
-        q.setPageSize(3);
-        q.addPrefetch("toArtist");
+        ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
+                .pageSize(3)
+                .prefetch("toArtist", PrefetchTreeNode.UNDEFINED_SEMANTICS);
 
         IncrementalFaultList<?> result = (IncrementalFaultList) context.performQuery(q);
 
         // get an objects from the second page
         final DataObject p1 = (DataObject) result.get(q.getPageSize());
 
-        queryInterceptor.runWithQueriesBlocked(new UnitTestClosure() {
-
-            public void execute() {
-                Object toOnePrefetch = p1.readNestedProperty("toArtist");
-                assertNotNull(toOnePrefetch);
-                assertTrue(
-                        "Expected DataObject, got: " + toOnePrefetch.getClass().getName(),
-                        toOnePrefetch instanceof DataObject);
+        queryInterceptor.runWithQueriesBlocked(() -> {
+            Object toOnePrefetch = p1.readNestedProperty("toArtist");
+            assertNotNull(toOnePrefetch);
+            assertTrue(
+                    "Expected DataObject, got: " + toOnePrefetch.getClass().getName(),
+                    toOnePrefetch instanceof DataObject);
 
-                DataObject a1 = (DataObject) toOnePrefetch;
-                assertEquals(PersistenceState.COMMITTED, a1.getPersistenceState());
-            }
+            DataObject a1 = (DataObject) toOnePrefetch;
+            assertEquals(PersistenceState.COMMITTED, a1.getPersistenceState());
         });
     }
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/SingleTableInheritance1IT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/SingleTableInheritance1IT.java
index 0a31c24..c4201bd 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/SingleTableInheritance1IT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/SingleTableInheritance1IT.java
@@ -20,9 +20,7 @@ package org.apache.cayenne.access;
 
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.testdo.inheritance_flat.Group;
 import org.apache.cayenne.testdo.inheritance_flat.Role;
 import org.apache.cayenne.testdo.inheritance_flat.User;
@@ -61,8 +59,8 @@ public class SingleTableInheritance1IT extends ServerCase {
 
         // Per CAY-1379 removing user and then refetching resulted in a FFE downstream
         group1.removeFromGroupMembers(user);
-        Expression exp = ExpressionFactory.matchExp(Role.ROLE_GROUPS.getName(), group2);
-        SelectQuery query = new SelectQuery(Group.class, exp);
+        ObjectSelect<Group> query = ObjectSelect.query(Group.class)
+                .where(Role.ROLE_GROUPS.contains(group2));
         context.performQuery(query);
         context.commitChanges();
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/SingleTableInheritanceIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/SingleTableInheritanceIT.java
index 32e8b27..fad3f24 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/SingleTableInheritanceIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/SingleTableInheritanceIT.java
@@ -19,10 +19,14 @@
 
 package org.apache.cayenne.access;
 
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.List;
+
 import org.apache.cayenne.Cayenne;
 import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.SQLTemplate;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.query.SortOrder;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.inheritance_people.AbstractPerson;
@@ -34,16 +38,14 @@ import org.apache.cayenne.testdo.inheritance_people.Employee;
 import org.apache.cayenne.testdo.inheritance_people.Manager;
 import org.apache.cayenne.testdo.inheritance_people.PersonNotes;
 import org.apache.cayenne.unit.di.DataChannelInterceptor;
-import org.apache.cayenne.unit.di.UnitTestClosure;
 import org.apache.cayenne.unit.di.server.PeopleProjectCase;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.sql.Types;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 
 public class SingleTableInheritanceIT extends PeopleProjectCase {
 
@@ -129,10 +131,9 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
         create2PersonDataSet();
 
         // fetch on leaf, but match on a super attribute
-        SelectQuery select = new SelectQuery(Manager.class);
-        select.andQualifier(AbstractPerson.NAME.eq("E2"));
-
-        List<Manager> results = context.performQuery(select);
+        List<Manager> results = ObjectSelect.query(Manager.class)
+                .and(AbstractPerson.NAME.eq("E2"))
+                .select(context);
         assertEquals(1, results.size());
         assertEquals("E2", results.get(0).getName());
     }
@@ -142,27 +143,22 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
         create2PersonDataSet();
 
         // fetch on leaf, but match on a super attribute
-        SelectQuery select = new SelectQuery(Employee.class);
-        select.addPrefetch(Employee.TO_DEPARTMENT.disjoint());
-        select.andQualifier(AbstractPerson.NAME.eq("E2"));
-
-        List<Manager> results = context.performQuery(select);
+        List<Employee> results = ObjectSelect.query(Employee.class)
+                .prefetch(Employee.TO_DEPARTMENT.disjoint())
+                .and(AbstractPerson.NAME.eq("E2"))
+                .select(context);
         assertEquals(1, results.size());
         assertEquals("E2", results.get(0).getName());
     }
 
     @Test
     public void testPaginatedQueries() throws Exception {
-
         create5PersonDataSet();
 
-        SelectQuery select = new SelectQuery(AbstractPerson.class);
-        select.addOrdering(
-                "db:" + AbstractPerson.PERSON_ID_PK_COLUMN,
-                SortOrder.ASCENDING);
-        select.setPageSize(3);
-
-        List<AbstractPerson> results = context.performQuery(select);
+        List<AbstractPerson> results = ObjectSelect.query(AbstractPerson.class)
+                .orderBy("db:" + AbstractPerson.PERSON_ID_PK_COLUMN, SortOrder.ASCENDING)
+                .pageSize(3)
+                .select(context);
         assertEquals(5, results.size());
 
         assertTrue(results.get(0) instanceof Employee);
@@ -205,8 +201,8 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
                 PersonNotes.class,
                 "INSERT INTO PERSON_NOTES (ID, NOTES, PERSON_ID) VALUES (4, 'BB', 3)"));
 
-        SelectQuery query = new SelectQuery(AbstractPerson.class);
-        query.addPrefetch(AbstractPerson.NOTES.joint());
+        ObjectSelect<AbstractPerson> query = ObjectSelect.query(AbstractPerson.class)
+                .prefetch(AbstractPerson.NOTES.joint());
 
         final AbstractPerson person = (AbstractPerson) Cayenne.objectForQuery(
                 context,
@@ -214,19 +210,16 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
 
         assertTrue(person instanceof Employee);
 
-        queryBlocker.runWithQueriesBlocked(new UnitTestClosure() {
+        queryBlocker.runWithQueriesBlocked(() -> {
+            assertEquals(2, person.getNotes().size());
 
-            public void execute() {
-                assertEquals(2, person.getNotes().size());
+            String[] names = new String[2];
+            names[0] = person.getNotes().get(0).getNotes();
+            names[1] = person.getNotes().get(1).getNotes();
+            List<String> nameSet = Arrays.asList(names);
 
-                String[] names = new String[2];
-                names[0] = person.getNotes().get(0).getNotes();
-                names[1] = person.getNotes().get(1).getNotes();
-                List<String> nameSet = Arrays.asList(names);
-
-                assertTrue(nameSet.contains("AA"));
-                assertTrue(nameSet.contains("BB"));
-            }
+            assertTrue(nameSet.contains("AA"));
+            assertTrue(nameSet.contains("BB"));
         });
     }
 
@@ -244,27 +237,24 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
                 PersonNotes.class,
                 "INSERT INTO PERSON_NOTES (ID, NOTES, PERSON_ID) VALUES (4, 'BB', 3)"));
 
-        SelectQuery query = new SelectQuery(AbstractPerson.class);
-        query.addPrefetch(AbstractPerson.NOTES.disjoint());
+        ObjectSelect<AbstractPerson> query = ObjectSelect.query(AbstractPerson.class)
+                .prefetch(AbstractPerson.NOTES.disjoint());
 
         final AbstractPerson person = (AbstractPerson) Cayenne.objectForQuery(
                 context,
                 query);
         assertTrue(person instanceof Employee);
 
-        queryBlocker.runWithQueriesBlocked(new UnitTestClosure() {
-
-            public void execute() {
-                assertEquals(2, person.getNotes().size());
+        queryBlocker.runWithQueriesBlocked(() -> {
+            assertEquals(2, person.getNotes().size());
 
-                String[] names = new String[2];
-                names[0] = person.getNotes().get(0).getNotes();
-                names[1] = person.getNotes().get(1).getNotes();
-                List<String> nameSet = Arrays.asList(names);
+            String[] names = new String[2];
+            names[0] = person.getNotes().get(0).getNotes();
+            names[1] = person.getNotes().get(1).getNotes();
+            List<String> nameSet = Arrays.asList(names);
 
-                assertTrue(nameSet.contains("AA"));
-                assertTrue(nameSet.contains("BB"));
-            }
+            assertTrue(nameSet.contains("AA"));
+            assertTrue(nameSet.contains("BB"));
         });
     }
 
@@ -283,20 +273,14 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
                 PersonNotes.class,
                 "INSERT INTO PERSON_NOTES (ID, NOTES, PERSON_ID) VALUES (3, 'BB', 2)"));
 
-        SelectQuery query = new SelectQuery(PersonNotes.class);
-        query.addPrefetch(PersonNotes.PERSON.disjoint());
-        query.addOrdering(PersonNotes.NOTES.asc());
-
-        List<PersonNotes> notes = context.performQuery(query);
+        List<PersonNotes> notes = ObjectSelect.query(PersonNotes.class)
+                .prefetch(PersonNotes.PERSON.disjoint())
+                .orderBy(PersonNotes.NOTES.asc())
+                .select(context);
         assertEquals(2, notes.size());
         final PersonNotes note = notes.get(0);
 
-        queryBlocker.runWithQueriesBlocked(new UnitTestClosure() {
-
-            public void execute() {
-                assertEquals("AA", note.getPerson().getName());
-            }
-        });
+        queryBlocker.runWithQueriesBlocked(() -> assertEquals("AA", note.getPerson().getName()));
     }
 
     @Test
@@ -310,17 +294,12 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
                 PersonNotes.class,
                 "INSERT INTO PERSON_NOTES (ID, NOTES, PERSON_ID) VALUES (3, 'AA', 3)"));
 
-        SelectQuery query = new SelectQuery(PersonNotes.class);
-        query.addPrefetch(PersonNotes.PERSON.joint());
+        ObjectSelect<PersonNotes> query = ObjectSelect.query(PersonNotes.class)
+                .prefetch(PersonNotes.PERSON.joint());
 
         final PersonNotes note = (PersonNotes) Cayenne.objectForQuery(context, query);
 
-        queryBlocker.runWithQueriesBlocked(new UnitTestClosure() {
-
-            public void execute() {
-                assertEquals("AA", note.getPerson().getName());
-            }
-        });
+        queryBlocker.runWithQueriesBlocked(() -> assertEquals("AA", note.getPerson().getName()));
 
     }
 
@@ -341,8 +320,8 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
         context.commitChanges();
         context.invalidateObjects(company, rep, employee);
 
-        SelectQuery query = new SelectQuery(CustomerRepresentative.class);
-        List<?> reps = context2.performQuery(query);
+        List<?> reps = ObjectSelect.query(CustomerRepresentative.class)
+                .select(context2);
 
         assertEquals(1, reps.size());
         assertEquals(1, countObjectOfClass(reps, CustomerRepresentative.class));
@@ -355,7 +334,8 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
     public void testEmployeeAddress() throws Exception {
         createEmployeeAddressDataSet();
 
-        List<?> addresses = context.performQuery(new SelectQuery(Address.class));
+        List<?> addresses = ObjectSelect.query(Address.class)
+                .select(context);
 
         assertEquals(1, addresses.size());
         Address address = (Address) addresses.get(0);
@@ -369,7 +349,8 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
     public void testManagerAddress() throws Exception {
         createManagerAddressDataSet();
 
-        List<?> addresses = context.performQuery(new SelectQuery(Address.class));
+        List<Address> addresses = ObjectSelect.query(Address.class)
+                .select(context);
 
         assertEquals(1, addresses.size());
         Address address = (Address) addresses.get(0);
@@ -382,10 +363,11 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
     public void testCAY592() throws Exception {
         createManagerAddressDataSet();
 
-        List<?> addresses = context.performQuery(new SelectQuery(Address.class));
+        List<Address> addresses = ObjectSelect.query(Address.class)
+                .select(context);
 
         assertEquals(1, addresses.size());
-        Address address = (Address) addresses.get(0);
+        Address address = addresses.get(0);
         Employee e = address.getToEmployee();
 
         // CAY-592 - make sure modification of the address in a parallel context
@@ -406,10 +388,11 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
     public void testRepCompany() throws Exception {
         createRepCompanyDataSet();
 
-        List<?> companies = context.performQuery(new SelectQuery(ClientCompany.class));
+        List<ClientCompany> companies = ObjectSelect.query(ClientCompany.class)
+                .select(context);
 
         assertEquals(1, companies.size());
-        ClientCompany company = (ClientCompany) companies.get(0);
+        ClientCompany company = companies.get(0);
         List<?> reps = company.getRepresentatives();
         assertEquals(1, reps.size());
         assertSame(CustomerRepresentative.class, reps.get(0).getClass());
@@ -422,10 +405,11 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
     public void testDepartmentEmployees() throws Exception {
         createDepartmentEmployeesDataSet();
 
-        List<?> departments = context.performQuery(new SelectQuery(Department.class));
+        List<Department> departments = ObjectSelect.query(Department.class)
+                .select(context);
 
         assertEquals(1, departments.size());
-        Department dept = (Department) departments.get(0);
+        Department dept = departments.get(0);
         List<?> employees = dept.getEmployees();
         assertEquals(3, employees.size());
         assertEquals(3, countObjectOfClass(employees, Employee.class));
@@ -436,8 +420,8 @@ public class SingleTableInheritanceIT extends PeopleProjectCase {
     public void testSelectInheritanceResolving() throws Exception {
         createSelectDataSet();
 
-        SelectQuery query = new SelectQuery(AbstractPerson.class);
-        List<?> abstractPpl = context.performQuery(query);
+        List<AbstractPerson> abstractPpl = ObjectSelect.query(AbstractPerson.class)
+                .select(context);
         assertEquals(6, abstractPpl.size());
 
         assertEquals(1, countObjectOfClass(abstractPpl, CustomerRepresentative.class));
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/UUIDIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/UUIDIT.java
index e6244e2..a0721e0 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/UUIDIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/UUIDIT.java
@@ -18,13 +18,14 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.util.UUID;
+
 import org.apache.cayenne.Cayenne;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.query.ObjectSelect;
-import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.uuid.UuidPkEntity;
@@ -35,8 +36,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.UUID;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
@@ -65,8 +64,8 @@ public class UUIDIT extends ServerCase {
         test.setUuid(id);
         context.commitChanges();
 
-        SelectQuery<UuidTestEntity> q = new SelectQuery<>(UuidTestEntity.class);
-        UuidTestEntity testRead = (UuidTestEntity) context.performQuery(q).get(0);
+        UuidTestEntity testRead = ObjectSelect.query(UuidTestEntity.class)
+                .selectFirst(context);
         assertNotNull(testRead.getUuid());
         assertEquals(id, testRead.getUuid());
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
index 5535838..e7734a1 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
@@ -18,6 +18,13 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
@@ -27,24 +34,25 @@ import org.apache.cayenne.query.SelectById;
 import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
-import org.apache.cayenne.testdo.inheritance_vertical.*;
+import org.apache.cayenne.testdo.inheritance_vertical.Iv1Root;
+import org.apache.cayenne.testdo.inheritance_vertical.Iv1Sub1;
+import org.apache.cayenne.testdo.inheritance_vertical.Iv2Sub1;
+import org.apache.cayenne.testdo.inheritance_vertical.Iv2X;
+import org.apache.cayenne.testdo.inheritance_vertical.IvConcrete;
+import org.apache.cayenne.testdo.inheritance_vertical.IvImpl;
+import org.apache.cayenne.testdo.inheritance_vertical.IvImplWithLock;
+import org.apache.cayenne.testdo.inheritance_vertical.IvOther;
+import org.apache.cayenne.testdo.inheritance_vertical.IvRoot;
+import org.apache.cayenne.testdo.inheritance_vertical.IvSub1;
+import org.apache.cayenne.testdo.inheritance_vertical.IvSub1Sub1;
+import org.apache.cayenne.testdo.inheritance_vertical.IvSub2;
+import org.apache.cayenne.testdo.inheritance_vertical.IvSub3;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
 import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Test;
 
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 @UseServerRuntime(CayenneProjects.INHERITANCE_VERTICAL_PROJECT)
 public class VerticalInheritanceIT extends ServerCase {
@@ -300,6 +308,7 @@ public class VerticalInheritanceIT extends ServerCase {
 	}
 
     @Test
+	@Deprecated
 	public void testSelectQuery_SuperSub() throws Exception {
 
 		TableHelper ivRootTable = new TableHelper(dbHelper, "IV_ROOT");
@@ -342,6 +351,7 @@ public class VerticalInheritanceIT extends ServerCase {
 	}
 
     @Test
+	@Deprecated
 	public void testSelectQuery_DeepAndWide() throws Exception {
 
 		TableHelper ivRootTable = new TableHelper(dbHelper, "IV_ROOT");
@@ -412,6 +422,7 @@ public class VerticalInheritanceIT extends ServerCase {
 	}
 
     @Test
+	@Deprecated
 	public void testSelectQuery_MiddleLeaf() throws Exception {
 
 		TableHelper ivRootTable = new TableHelper(dbHelper, "IV_ROOT");
@@ -530,6 +541,7 @@ public class VerticalInheritanceIT extends ServerCase {
 	}
 
     @Test
+	@Deprecated
 	public void testSelectQuery_AttributeOverrides() throws Exception {
 
 		TableHelper iv1RootTable = new TableHelper(dbHelper, "IV1_ROOT");


Mime
View raw message