cayenne-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andrus Adamchik <>
Subject Re: Chainable SelectQuery
Date Sat, 11 Oct 2014 01:06:52 GMT
I think this was a very productive discussion. Based on it and some more thinking, here is
my takeaway:

1. Instead of drastically redoing good old SelectQuery, we'll create a separate class called
ObjectSelect featuring fluent API. No deprecations in SelectQuery. In fact the existing API
still appears to be very useful in dynamic query configuration scenarios. I encounter them
rather often in framework'y code where the decisions need to be made based on preconfigured

1a. if(cachePolicy == LOCAL_CACHE) {



1b. SelectQuery<?> q;
    if(fetchDataRows) {
       q = SelectQuery.dataRowsQuery(type);
    else {
       q = SelectQuery.query(type);


   SelectQuery q = new SelectQuery(type);

Also cases when you need to reset/replace previous settings. So both styles have their use.

2. Instead of "qualifier" the new query might just use "exp" (in addition to "and" and "or").

3. ExpressionFactory.exp(..) and ObjectSelect.exp(..) should allow for both named parameter
binding as well as vararg positional binding.

4. Still need to come up with fluent API for orderings and prefetches. Separation from SelectQuery
should simplify this task.

5. The last method in a chain doesn't have to be limited to "select" and "selectOne". It can
be query-specific, depending on what operations a given query supports. E.g. we can have queries
with "count(context)", etc. This is something we should explore.

6. Corollary to #5, we should explore iterator methods in query chains (need to make sure
that we don't reinvent the wheels invented in Java 8).

7. Non-selecting queries should use such API too. E.g. in addition to SQLSelect we might have
SQLOperation with chain terminating with "int update(context)" or "int[] batchUpdate(context)"
or "QueryResponse exec(context)". Same goes for ProcedureQuery.


On Oct 5, 2014, at 11:10 AM, Andrus Adamchik <> wrote:

> In preparation to 3.2.M2, I am working on polishing our new query APIs. Good examples
of the new API are a new SelectById query [1] and of course previously available SQLSelect.
Now started working on SelectQuery, which is a more subtle matter as it affects every single
Cayenne user. So instead of committing it right away, I created a pull request #16 [2] and
now would like to hear comments before this goes to the main repo.
> This changes SelectQuery and tweaks ExpressionFactory and Expression. You get the most
milage out of it if you statically import ExpressionFactory. A good example is the Main file
from our tutorials [3]:
> // static imports
> import static org.apache.cayenne.exp.ExpressionFactory.exp;
> import static org.apache.cayenne.exp.ExpressionFactory.or;
> ...
> // a single chain from query to object list
> List<Painting> paintings2 = SelectQuery.query(Painting.class, qualifier2).select(context);
> ...
> // static use of "exp" (former "Expression.fromString")
> // immediate parameter binding
> Expression qualifier3 = exp("artist.dateOfBirth < $date", "date", c.getTime());
> // static use of 'or' seems cleaner than chaining expressions with 'exp.orExp(..)'
> List<Painting> paintings4 = SelectQuery.query(Painting.class, or(qualifier2, qualifier3)).select(context);
> Comments?
> Andrus
> [1]
> [2]
> [3]

View raw message