cayenne-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From John Huss <johnth...@gmail.com>
Subject Re: Chainable SelectQuery
Date Tue, 07 Oct 2014 14:31:42 GMT
Hmm... I have a lot to say, so I might ramble a bit.

1) Static imports

I'll never been a big user of static imports, largely because the tooling
(Eclipse) doesn't support them well.  Everytime I've used a static import
(which is really only in JUnit) I've wanted to import all the members:
import package.*;  Well, when you organize import Eclipse will replace the
star with the specific items you've used.  So you end up have to fix the
import over and over.  On the other side, Eclipse won't automatically add
the static import or even recommend it based on your code, so it becomes a
rarely used feature.

Another option is to just use a very short class name, which is something
Project Wonder did (also they didn't have the option of changing the
original).  They have a class ERXQ which acts just like ExpressionFactory.
Minus the ERX convention, this becomes a single letter - Q.  I wouldn't
recommend renaming ExpressionFactory to that, but you could have a subclass
of it that could be used just to get a shorter name.

That said, it may all be mute, because I never use any of the static
methods in ExpressionFactory since I build all my expressions using the
generated Property constants in each entity class.

I like the shorter method names.

2) SelectQuery

I'm not a fan of methods that return "this" because it is impossible to
tell (without looking at javadoc) whether a new instance or the same
instance is returned.  In this case even the javadoc doesn't tell you.
Having adopted more of a functional programming mindset in the last few
years, I would be much more interested in an immutable SelectQuery class
that returns copies, or with a builder and an immutable class.  One benefit
to that approach (besides being easier to reason about passing them around)
is that queries can safely be stored as constants and reused.  Of course,
making it immutable wouldn't be backwards compatible so probably a new
class would have to be written in it's place.

That said, if returning this is the direction we're going, then really all
the currently void methods in SelectQuery should do the same thing - like
addOrdering for example.

I'm not sure I like adding the select and selectOne methods on to
SelectQuery because then you have more than one way to do the same thing,
but with little advantage:

context.select(query)   vs
query.select(context)

Personally, I prefer to keep the select at the front to make it read like
SQL.  I'd prefer something like this:

context.select(SelectQuery.query(Artist.class).where(NAME.eq("Picasso")).orderBy(NAME.asc()).limit(1);

or course longer constructor can be used instead, but it is arguably less
readable.

context.select(SelectQuery.query(Artist.class, NAME.eq("Picasso"),
NAME.ascs()).limit(1);

I'd take a bit to examine other ORMs to see what their APIs look like for
this.

All said, I'm glad to see movement happening on this!

John


On Sun, Oct 5, 2014 at 10:10 AM, Andrus Adamchik <andrus@objectstyle.org>
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]
> https://github.com/apache/cayenne/blob/master/cayenne-server/src/main/java/org/apache/cayenne/query/SelectById.java
> [2] https://github.com/apache/cayenne/pull/16
> [3]
> https://github.com/andrus/cayenne/blob/9dca05242d393aba5892b6ce33e36fc7e2078bca/tutorials/tutorial/src/main/java/org/apache/cayenne/tutorial/Main.java

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message