FAQ
Any thoughts on updating SelectQuery.java to handle Orderings as:

SelectQuery(Class, Expression, Ordering) or
SelectQuery(Class, Expression, List<Ordering>) or
SelectQuery(Class, Expression, Ordering...) or
public SelectQuery addOrdering(Ordering ordering) and
public SelectQuery addOrderings(List<Ordering> orderings) ...

I'm personally thinking the last, so it is chainable.

Thanks,

mrg

Search Discussions

  • John Huss at Jan 26, 2012 at 6:00 pm
    SelectQuery(Class, Expression, List<Ordering>)

    This one would be helpful for people migrating from WebObjects.
    On Thu, Jan 26, 2012 at 11:15 AM, Michael Gentry wrote:

    Any thoughts on updating SelectQuery.java to handle Orderings as:

    SelectQuery(Class, Expression, Ordering) or
    SelectQuery(Class, Expression, List<Ordering>) or
    SelectQuery(Class, Expression, Ordering...) or
    public SelectQuery addOrdering(Ordering ordering) and
    public SelectQuery addOrderings(List<Ordering> orderings) ...

    I'm personally thinking the last, so it is chainable.

    Thanks,

    mrg
  • Aristedes Maniatis at Jan 27, 2012 at 1:03 am

    On 27/01/12 4:15 AM, Michael Gentry wrote:
    Any thoughts on updating SelectQuery.java to handle Orderings as:

    SelectQuery(Class, Expression, Ordering) or
    SelectQuery(Class, Expression, List<Ordering>) or
    SelectQuery(Class, Expression, Ordering...) or
    public SelectQuery addOrdering(Ordering ordering) and
    public SelectQuery addOrderings(List<Ordering> orderings) ...

    I'm personally thinking the last, so it is chainable.
    Purely from a naming point of view, both of these:

    public SelectQuery order(Ordering ordering)
    public SelectQuery order(List<Ordering> orderings)

    This is then chainable, and will read very nicely, particularly when combined with similar functions for "limit", "join/prefetch", etc.



    Ari


    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
  • Andrus Adamchik at Jan 27, 2012 at 7:12 am
    IMO all of the suggestions are good. Summarizing:

    1. SelectQuery(Class<?>, Expression) becomes an equivalent SelectQuery(Class<?>, Expression, Ordering...)
    2. (new) SelectQuery(Class<?>, Expression, List<Ordering>)
    3. (new) SelectQuery order(String, SortOrder)
    4. (new) SelectQuery order(Ordering... ordering)
    5. (new) SelectQuery order(List<Ordering> orderings)

    6. (deprecated) void addOrdering / addOrderings
    On Jan 27, 2012, at 4:02 AM, Aristedes Maniatis wrote:
    On 27/01/12 4:15 AM, Michael Gentry wrote:
    Any thoughts on updating SelectQuery.java to handle Orderings as:

    SelectQuery(Class, Expression, Ordering) or
    SelectQuery(Class, Expression, List<Ordering>) or
    SelectQuery(Class, Expression, Ordering...) or
    public SelectQuery addOrdering(Ordering ordering) and
    public SelectQuery addOrderings(List<Ordering> orderings) ...

    I'm personally thinking the last, so it is chainable.
    Purely from a naming point of view, both of these:

    public SelectQuery order(Ordering ordering)
    public SelectQuery order(List<Ordering> orderings)

    This is then chainable, and will read very nicely, particularly when combined with similar functions for "limit", "join/prefetch", etc.



    Ari


    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
  • Michael Gentry at Jan 27, 2012 at 1:39 pm
    My only quibble with order() is it sounds immediate. Maybe orderBy()
    instead? For fetch limits, could have a limitTo() method?

    Thanks,

    mrg

    On Fri, Jan 27, 2012 at 2:11 AM, Andrus Adamchik wrote:
    IMO all of the suggestions are good. Summarizing:

    1. SelectQuery(Class<?>, Expression) becomes an equivalent SelectQuery(Class<?>, Expression, Ordering...)
    2. (new) SelectQuery(Class<?>, Expression, List<Ordering>)
    3. (new) SelectQuery order(String, SortOrder)
    4. (new) SelectQuery order(Ordering... ordering)
    5. (new) SelectQuery order(List<Ordering> orderings)

    6. (deprecated) void addOrdering / addOrderings
    On Jan 27, 2012, at 4:02 AM, Aristedes Maniatis wrote:
    On 27/01/12 4:15 AM, Michael Gentry wrote:
    Any thoughts on updating SelectQuery.java to handle Orderings as:

    SelectQuery(Class, Expression, Ordering) or
    SelectQuery(Class, Expression, List<Ordering>) or
    SelectQuery(Class, Expression, Ordering...) or
    public SelectQuery addOrdering(Ordering ordering) and
    public SelectQuery addOrderings(List<Ordering>  orderings) ...

    I'm personally thinking the last, so it is chainable.
    Purely from a naming point of view, both of these:

    public SelectQuery order(Ordering ordering)
    public SelectQuery order(List<Ordering> orderings)

    This is then chainable, and will read very nicely, particularly when combined with similar functions for "limit", "join/prefetch", etc.



    Ari


    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A
  • Andrus Adamchik at Jan 27, 2012 at 1:52 pm

    My only quibble with order() is it sounds immediate. Maybe orderBy()
    instead?
    Fine with me.
    For fetch limits, could have a limitTo() method?
    FetchLimit is a bit different - it a "property" in a Java beans sense. The ordering API changes do not affect the "property" aspect of it. So what is the goal here, to provide chainable API?

    Andrus

    On Jan 27, 2012, at 4:38 PM, Michael Gentry wrote:

    My only quibble with order() is it sounds immediate. Maybe orderBy()
    instead? For fetch limits, could have a limitTo() method?

    Thanks,

    mrg

    On Fri, Jan 27, 2012 at 2:11 AM, Andrus Adamchik wrote:
    IMO all of the suggestions are good. Summarizing:

    1. SelectQuery(Class<?>, Expression) becomes an equivalent SelectQuery(Class<?>, Expression, Ordering...)
    2. (new) SelectQuery(Class<?>, Expression, List<Ordering>)
    3. (new) SelectQuery order(String, SortOrder)
    4. (new) SelectQuery order(Ordering... ordering)
    5. (new) SelectQuery order(List<Ordering> orderings)

    6. (deprecated) void addOrdering / addOrderings
    On Jan 27, 2012, at 4:02 AM, Aristedes Maniatis wrote:
    On 27/01/12 4:15 AM, Michael Gentry wrote:
    Any thoughts on updating SelectQuery.java to handle Orderings as:

    SelectQuery(Class, Expression, Ordering) or
    SelectQuery(Class, Expression, List<Ordering>) or
    SelectQuery(Class, Expression, Ordering...) or
    public SelectQuery addOrdering(Ordering ordering) and
    public SelectQuery addOrderings(List<Ordering> orderings) ...

    I'm personally thinking the last, so it is chainable.
    Purely from a naming point of view, both of these:

    public SelectQuery order(Ordering ordering)
    public SelectQuery order(List<Ordering> orderings)

    This is then chainable, and will read very nicely, particularly when combined with similar functions for "limit", "join/prefetch", etc.



    Ari


    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
  • Michael Gentry at Jan 27, 2012 at 2:07 pm
    Chainable was kind of an afterthought. I mentioned limits because Ari
    did. Basically I've been creating a lot of queries lately and then
    after creating them, adding the ordering separately. Just seemed a
    tad clunkier that way, so I was trying to think of ways to make it a
    bit cleaner.

    Thanks,

    mrg

    On Fri, Jan 27, 2012 at 8:51 AM, Andrus Adamchik wrote:
    My only quibble with order() is it sounds immediate.  Maybe orderBy()
    instead?
    Fine with me.
    For fetch limits, could have a limitTo() method?
    FetchLimit is a bit different - it a "property" in a Java beans sense. The ordering API changes do not affect the "property" aspect of it. So what is the goal here, to provide chainable API?

    Andrus

    On Jan 27, 2012, at 4:38 PM, Michael Gentry wrote:

    My only quibble with order() is it sounds immediate.  Maybe orderBy()
    instead?  For fetch limits, could have a limitTo() method?

    Thanks,

    mrg

    On Fri, Jan 27, 2012 at 2:11 AM, Andrus Adamchik wrote:
    IMO all of the suggestions are good. Summarizing:

    1. SelectQuery(Class<?>, Expression) becomes an equivalent SelectQuery(Class<?>, Expression, Ordering...)
    2. (new) SelectQuery(Class<?>, Expression, List<Ordering>)
    3. (new) SelectQuery order(String, SortOrder)
    4. (new) SelectQuery order(Ordering... ordering)
    5. (new) SelectQuery order(List<Ordering> orderings)

    6. (deprecated) void addOrdering / addOrderings
    On Jan 27, 2012, at 4:02 AM, Aristedes Maniatis wrote:
    On 27/01/12 4:15 AM, Michael Gentry wrote:
    Any thoughts on updating SelectQuery.java to handle Orderings as:

    SelectQuery(Class, Expression, Ordering) or
    SelectQuery(Class, Expression, List<Ordering>) or
    SelectQuery(Class, Expression, Ordering...) or
    public SelectQuery addOrdering(Ordering ordering) and
    public SelectQuery addOrderings(List<Ordering>  orderings) ...

    I'm personally thinking the last, so it is chainable.
    Purely from a naming point of view, both of these:

    public SelectQuery order(Ordering ordering)
    public SelectQuery order(List<Ordering> orderings)

    This is then chainable, and will read very nicely, particularly when combined with similar functions for "limit", "join/prefetch", etc.



    Ari


    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A
  • Andrus Adamchik at Jan 27, 2012 at 2:14 pm
    More on this topic - I usually don't use SelectQuery(..., Expression) constructor, as chaining Expressions is much more clunky than using query.andQualifier(..) / query.orQualifier(..). The only case is nested expressions whose parts can't be simply appended to the query.

    Andrus
    On Jan 27, 2012, at 5:06 PM, Michael Gentry wrote:

    Chainable was kind of an afterthought. I mentioned limits because Ari
    did. Basically I've been creating a lot of queries lately and then
    after creating them, adding the ordering separately. Just seemed a
    tad clunkier that way, so I was trying to think of ways to make it a
    bit cleaner.

    Thanks,

    mrg

    On Fri, Jan 27, 2012 at 8:51 AM, Andrus Adamchik wrote:
    My only quibble with order() is it sounds immediate. Maybe orderBy()
    instead?
    Fine with me.
    For fetch limits, could have a limitTo() method?
    FetchLimit is a bit different - it a "property" in a Java beans sense. The ordering API changes do not affect the "property" aspect of it. So what is the goal here, to provide chainable API?

    Andrus

    On Jan 27, 2012, at 4:38 PM, Michael Gentry wrote:

    My only quibble with order() is it sounds immediate. Maybe orderBy()
    instead? For fetch limits, could have a limitTo() method?

    Thanks,

    mrg

    On Fri, Jan 27, 2012 at 2:11 AM, Andrus Adamchik wrote:
    IMO all of the suggestions are good. Summarizing:

    1. SelectQuery(Class<?>, Expression) becomes an equivalent SelectQuery(Class<?>, Expression, Ordering...)
    2. (new) SelectQuery(Class<?>, Expression, List<Ordering>)
    3. (new) SelectQuery order(String, SortOrder)
    4. (new) SelectQuery order(Ordering... ordering)
    5. (new) SelectQuery order(List<Ordering> orderings)

    6. (deprecated) void addOrdering / addOrderings
    On Jan 27, 2012, at 4:02 AM, Aristedes Maniatis wrote:
    On 27/01/12 4:15 AM, Michael Gentry wrote:
    Any thoughts on updating SelectQuery.java to handle Orderings as:

    SelectQuery(Class, Expression, Ordering) or
    SelectQuery(Class, Expression, List<Ordering>) or
    SelectQuery(Class, Expression, Ordering...) or
    public SelectQuery addOrdering(Ordering ordering) and
    public SelectQuery addOrderings(List<Ordering> orderings) ...

    I'm personally thinking the last, so it is chainable.
    Purely from a naming point of view, both of these:

    public SelectQuery order(Ordering ordering)
    public SelectQuery order(List<Ordering> orderings)

    This is then chainable, and will read very nicely, particularly when combined with similar functions for "limit", "join/prefetch", etc.



    Ari


    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
  • Michael Gentry at Jan 29, 2012 at 2:11 pm
    Am I the only one that finds andQualifier(Expression),
    orQualifier(Expression), setQualifier(Expression), and Expression
    getQualifier() to be odd?

    Qualifiers came out of WebObjects, but Cayenne uses Expression. Seems
    to me those should be andExpression(Expression) ...

    mrg

    On Fri, Jan 27, 2012 at 9:13 AM, Andrus Adamchik wrote:
    More on this topic -  I usually don't use SelectQuery(..., Expression) constructor, as chaining Expressions is much more clunky than using query.andQualifier(..) / query.orQualifier(..). The only case is nested expressions whose parts can't be simply appended to the query.

    Andrus
    On Jan 27, 2012, at 5:06 PM, Michael Gentry wrote:

    Chainable was kind of an afterthought.  I mentioned limits because Ari
    did.  Basically I've been creating a lot of queries lately and then
    after creating them, adding the ordering separately.  Just seemed a
    tad clunkier that way, so I was trying to think of ways to make it a
    bit cleaner.

    Thanks,

    mrg

    On Fri, Jan 27, 2012 at 8:51 AM, Andrus Adamchik wrote:
    My only quibble with order() is it sounds immediate.  Maybe orderBy()
    instead?
    Fine with me.
    For fetch limits, could have a limitTo() method?
    FetchLimit is a bit different - it a "property" in a Java beans sense. The ordering API changes do not affect the "property" aspect of it. So what is the goal here, to provide chainable API?

    Andrus

    On Jan 27, 2012, at 4:38 PM, Michael Gentry wrote:

    My only quibble with order() is it sounds immediate.  Maybe orderBy()
    instead?  For fetch limits, could have a limitTo() method?

    Thanks,

    mrg

    On Fri, Jan 27, 2012 at 2:11 AM, Andrus Adamchik wrote:
    IMO all of the suggestions are good. Summarizing:

    1. SelectQuery(Class<?>, Expression) becomes an equivalent SelectQuery(Class<?>, Expression, Ordering...)
    2. (new) SelectQuery(Class<?>, Expression, List<Ordering>)
    3. (new) SelectQuery order(String, SortOrder)
    4. (new) SelectQuery order(Ordering... ordering)
    5. (new) SelectQuery order(List<Ordering> orderings)

    6. (deprecated) void addOrdering / addOrderings
    On Jan 27, 2012, at 4:02 AM, Aristedes Maniatis wrote:
    On 27/01/12 4:15 AM, Michael Gentry wrote:
    Any thoughts on updating SelectQuery.java to handle Orderings as:

    SelectQuery(Class, Expression, Ordering) or
    SelectQuery(Class, Expression, List<Ordering>) or
    SelectQuery(Class, Expression, Ordering...) or
    public SelectQuery addOrdering(Ordering ordering) and
    public SelectQuery addOrderings(List<Ordering>  orderings) ...

    I'm personally thinking the last, so it is chainable.
    Purely from a naming point of view, both of these:

    public SelectQuery order(Ordering ordering)
    public SelectQuery order(List<Ordering> orderings)

    This is then chainable, and will read very nicely, particularly when combined with similar functions for "limit", "join/prefetch", etc.



    Ari


    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A
  • Andrus Adamchik at Jan 30, 2012 at 7:23 am
    In the dawn of Cayenne we had this (IIRC offline) discussion with Andriy. The point he made was that "expression" is abstract, while "qualifier" is an expression attached to a query. I.e. "qualifier" is a name of the query attribute that happens to be an expression.

    I accepted this logic back then, but then and now I am neutral to either flavor of naming.

    Andrus


    On Jan 29, 2012, at 5:10 PM, Michael Gentry wrote:

    Am I the only one that finds andQualifier(Expression),
    orQualifier(Expression), setQualifier(Expression), and Expression
    getQualifier() to be odd?

    Qualifiers came out of WebObjects, but Cayenne uses Expression. Seems
    to me those should be andExpression(Expression) ...

    mrg

    On Fri, Jan 27, 2012 at 9:13 AM, Andrus Adamchik wrote:
    More on this topic - I usually don't use SelectQuery(..., Expression) constructor, as chaining Expressions is much more clunky than using query.andQualifier(..) / query.orQualifier(..). The only case is nested expressions whose parts can't be simply appended to the query.

    Andrus
    On Jan 27, 2012, at 5:06 PM, Michael Gentry wrote:

    Chainable was kind of an afterthought. I mentioned limits because Ari
    did. Basically I've been creating a lot of queries lately and then
    after creating them, adding the ordering separately. Just seemed a
    tad clunkier that way, so I was trying to think of ways to make it a
    bit cleaner.

    Thanks,

    mrg

    On Fri, Jan 27, 2012 at 8:51 AM, Andrus Adamchik wrote:
    My only quibble with order() is it sounds immediate. Maybe orderBy()
    instead?
    Fine with me.
    For fetch limits, could have a limitTo() method?
    FetchLimit is a bit different - it a "property" in a Java beans sense. The ordering API changes do not affect the "property" aspect of it. So what is the goal here, to provide chainable API?

    Andrus

    On Jan 27, 2012, at 4:38 PM, Michael Gentry wrote:

    My only quibble with order() is it sounds immediate. Maybe orderBy()
    instead? For fetch limits, could have a limitTo() method?

    Thanks,

    mrg

    On Fri, Jan 27, 2012 at 2:11 AM, Andrus Adamchik wrote:
    IMO all of the suggestions are good. Summarizing:

    1. SelectQuery(Class<?>, Expression) becomes an equivalent SelectQuery(Class<?>, Expression, Ordering...)
    2. (new) SelectQuery(Class<?>, Expression, List<Ordering>)
    3. (new) SelectQuery order(String, SortOrder)
    4. (new) SelectQuery order(Ordering... ordering)
    5. (new) SelectQuery order(List<Ordering> orderings)

    6. (deprecated) void addOrdering / addOrderings
    On Jan 27, 2012, at 4:02 AM, Aristedes Maniatis wrote:
    On 27/01/12 4:15 AM, Michael Gentry wrote:
    Any thoughts on updating SelectQuery.java to handle Orderings as:

    SelectQuery(Class, Expression, Ordering) or
    SelectQuery(Class, Expression, List<Ordering>) or
    SelectQuery(Class, Expression, Ordering...) or
    public SelectQuery addOrdering(Ordering ordering) and
    public SelectQuery addOrderings(List<Ordering> orderings) ...

    I'm personally thinking the last, so it is chainable.
    Purely from a naming point of view, both of these:

    public SelectQuery order(Ordering ordering)
    public SelectQuery order(List<Ordering> orderings)

    This is then chainable, and will read very nicely, particularly when combined with similar functions for "limit", "join/prefetch", etc.



    Ari


    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
  • Durchholz, Joachim at Jan 30, 2012 at 10:12 am
    +1 on using a chained query builder similar to that for Ruby/Rails.
    Am I the only one that finds andQualifier(Expression),
    orQualifier(Expression), setQualifier(Expression),
    and Expression getQualifier() to be odd?
    As an application developer, I'd find either far too verbose. I want something where I know from context what I'm talking about, because I'm typically writing a heap of conditions, so it's enough to write it once.

    E.g. it could be
    new QualifierList ()
    .like("name", "b%")
    .or (new QualifierList ()
    .greater("age", 23)
    .less("age", 27)
    )

    The QualifierList constructor and the first qualifier can be merged into one if writing a small subclass of QualifierList is in order:
    class Greater extends QualifierList {
    Greater(String property, int value) {
    super ();
    this.greater(property, value);
    }
    }
    giving
    new QualifierList ()
    .like("name", "b%")
    .or (
    new Greater("age", 23)
    .less("age", 27)
    )

    The same technique could be applied to Aristedes' example:

    SelectQuery(Artist.class)
    .like("name", "b%")
    .or (
    new Greater("age", 23)
    .less("age", 27)
    )
    .join(Gallery.class)
    .limit(10)
    .order(Artist.name)
    .perform()

    .like, .or, .greater, .less would then delegate to SelectQuery's member
    QualifierList whereConditions
    (which would need to be merged using AND when generating SQL)


    Note that these are still Expressions, not Qualifiers, since the lists can exist independently of a query.
    In fact it makes a lot of sense; SQL conditions for a table might be reused across queries. (Yes I know this is usually done via RDBMS views. Unfortunately, at least Oracle is extremely poor at providing key and column metadata for views.)


    Just providing data points :-)

    Regards,
    Jo
  • Aristedes Maniatis at Jan 30, 2012 at 11:22 am

    On 30/01/12 9:12 PM, Durchholz, Joachim wrote:

    giving
    new QualifierList ()
    .like("name", "b%")
    .or (
    new Greater("age", 23)
    .less("age", 27)
    )
    I am not sure you have achieved any more readability over the plain string version. Compare:

    new SelectQuery().query("age < 27")

    new SelectQuery().less("age", 27)

    Which parameter is supposed to be less than which? At any rate a more interesting approach might be to implement typesafe Object Attributes such as Artist.AGE<Integer>:

    less(ObjAttribute<T>, Object<T>)



    A more radical approach was also discussed before. Something like (from memory):

    new SelectQuery().and(Artist.AGE.under(23))

    It reads nicely and can be made type-safe, but is a bit messy in that it moves many Expression methods into the ObjAttribute class.




    Ari



    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
  • Durchholz, Joachim at Jan 30, 2012 at 11:58 am
    -----Original Message-----
    From: Aristedes Maniatis
    Sent: Monday, January 30, 2012 12:21 PM
    To: dev@cayenne.apache.org
    Subject: Re: SelectQuery + Orderings
    On 30/01/12 9:12 PM, Durchholz, Joachim wrote:

    giving
    new QualifierList ()
    .like("name", "b%")
    .or (
    new Greater("age", 23)
    .less("age", 27)
    )
    I am not sure you have achieved any more readability over the plain string version.
    Compare:

    new SelectQuery().query("age < 27")

    new SelectQuery().less("age", 27)

    Oh, that was more a presentational afterthought, not the actual issue.
    The background is that if you allow literals in query strings, it's getting seductive to write conditions like
    new SelectQuery().query("age < " + userInput)
    and get an SQL injection problem.
    Which parameter is supposed to be less than which?
    Left side is less than right side.
    Hibernate is using this idiom in its Criteria queries, and while I have many gripes with Hibernate, this particular decision never causes any problem for me.
    A more radical approach was also discussed before.
    Aww, the last weeks were a bit busy, so I probably missed that one.
    Something like (from memory):

    new SelectQuery().and(Artist.AGE.under(23))
    I'd introduce a standard abbreviation that SelectQuery() is automatically accepting conditions just like and() does.
    It reads nicely and can be made type-safe, but is a bit messy
    in that it moves many Expression methods into the ObjAttribute class.
    I can't say much about messiness - I have done my part in writing ORM code, but I haven't had the time to take an actual look at Cayenne's sources, so in the end, my perspective is more that of an application programmer (Cayenne user) than that of a Cayenne developer.

    However, I like that idiom very much, though I'd like to make it more concise.
    My last example would look like this:

    SelectQuery(Artist.class)
    .and(
    .Artist.NAME.isLike("b%")
    .or(
    Artist.AGE.above(23),
    Artist.AGE.below(27)
    )
    )
    .join(Gallery.class)
    .Gallery.COUNTRY.eq("UK")
    .limit(10)
    .order(Artist.name)
    .perform()

    Hm. What's nice about this is that it can be made type-safe and everything.
    What's not so nice is that we have to repeat Artist. all over the place.

    How about this one:

    Artist.query()
    .and(
    .NAME.isLike("b%")
    .or(
    Artist.conditions() // FAIL
    .AGE.above(23),
    .AGE.below(27)
    )
    .join(Gallery.class)
    .COUNTRY.eq("UK")
    .limit(10)
    .order(Artist.name)
    .perform()

    I don't like the line marked FAIL, it's two tokens (Artist and conditions) just to make Java happy.
    I'll have to come up with something better. Maybe make the nesting structure explicit with an .end() call:

    Artist.query()
    .and()
    .NAME.isLike("b%")
    .or()
    .AGE.above(23)
    .AGE.below(27)
    .end()
    .end() // redundant
    .order()
    .NAME
    .end() // redundant
    .join(Gallery.class)
    .COUNTRY.eq("UK")
    .perform()

    Some of the .end() calls are redundant and could be eliminated.
    It's still relatively compact, at the price of the occasional end() - those marked with "redundant" probably could be eliminated, so it's not so bad.

    This all smells like a generalized type-safe expression builder trying to get out.

    Unfortunately, I won't be able make this into a proof of concept, much less program it, so I'm limited to providing food for thought. Hope it helps - if not, please ignore :-)

    Regards,
    Jo
  • Aristedes Maniatis at Jan 30, 2012 at 12:09 pm

    On 30/01/12 10:57 PM, Durchholz, Joachim wrote:

    This all smells like a generalized type-safe expression builder trying to get out.

    Unfortunately, I won't be able make this into a proof of concept, much less program it, so I'm limited to providing food for thought. Hope it helps - if not, please ignore :-)

    I am thinking this is a good candidate to create a little github project with just bare interfaces, javadocs and method declarations for these important classes. Then everyone can fork it with their own ideas and the winner gets a fully paid trip for two... oh wait, no. But it could be fun.


    Ari


    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
  • Durchholz, Joachim at Jan 30, 2012 at 12:19 pm

    I am thinking this is a good candidate to create a little
    github project with just bare interfaces, javadocs and
    method declarations for these important classes. Then
    everyone can fork it with their own ideas and the winner
    gets a fully paid trip for two... oh wait, no. But it could be fun.
    Heh.
    I'm in :-)
  • Gilbertoca at Jan 30, 2012 at 1:59 pm
    Hi, hope everyone is doing well and having a great weekend!

    Good discussion. I'm not an expert on it, but I would like to make a little
    observation about it: inevitably, now or later you will need to create a
    complex query and a good api helps on it. I've worked on a little project
    with the queydls[1] API and so far so good - using EclipseLink.
    I think this query style would increase our productivity immensely.
    Regards,

    [1]
    http://www.querydsl.com/static/querydsl/2.3.0/reference/html/ch02.html#d0e185

    --
    View this message in context: http://cayenne.195.n3.nabble.com/SelectQuery-Orderings-tp3691025p3700046.html
    Sent from the Cayenne - Dev mailing list archive at Nabble.com.
  • John Huss at Jan 30, 2012 at 4:36 pm
    The qualifier building part has already been done in WebObjects/Project
    Wonder with ERXKey<http://webobjects.mdimension.com/hudson/job/Wonder/javadoc/>which
    is basically just a wrapper around an attribute or relationship name
    that gives it type-safety and a bunch of methods for creating qualifiers.
    These "key" object are part of the entity template so they are generated
    automatically. You can also generate a path builder class so you can do
    the same thing for related objects too. For example:

    Artist.NAME.eq("Picasso") // equals
    Artist.DATE_OF_BIRTH.lt(now()) // less than

    Or with paths:

    Painting.path.artist().name().eq("Picasso")

    Hugi Thordarson posted a pared-down version of ERXKey a while back here:
    https://bitbucket.org/hugi/jambalaya
    On Mon, Jan 30, 2012 at 6:08 AM, Aristedes Maniatis wrote:

    On 30/01/12 10:57 PM, Durchholz, Joachim wrote:

    This all smells like a generalized type-safe expression builder trying to
    get out.

    Unfortunately, I won't be able make this into a proof of concept, much
    less program it, so I'm limited to providing food for thought. Hope it
    helps - if not, please ignore :-)

    I am thinking this is a good candidate to create a little github project
    with just bare interfaces, javadocs and method declarations for these
    important classes. Then everyone can fork it with their own ideas and the
    winner gets a fully paid trip for two... oh wait, no. But it could be fun.



    Ari


    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
  • Durchholz, Joachim at Jan 31, 2012 at 10:13 am

    You can also generate a path builder class so you can
    do the same thing for related objects too. For example:

    Artist.NAME.eq("Picasso") // equals
    Artist.DATE_OF_BIRTH.lt(now()) // less than
    Having to repeat Artist. all over the place is exactly what I'd like to get rid of.

    Hmm...
    ...
    ... I see it's hard to see whether that's actually a problem or not.
    I see myself arguing on matters of principle, which is nice but risks failure when confronted with reality.
    I also see John arguing with small examples, which is nice but risks failure when trying to scale to complicated queries.

    How about if everybody with an interest in the topic scour their projects for the nastiest SQL that they have, and present them here?
    We'd have a set of use cases that will really test the various approaches.

    Regards
    Jo
  • John Huss at Jan 31, 2012 at 8:31 pm
    Well, if your code is well designed your artist fetch logic is probably in
    the Artist class so the class name isn't needed. If you are doing
    something inside the class you can use a static import to move all the
    artist stuff into the namespace and then use it without qualification.
    On Tuesday, January 31, 2012, Durchholz, Joachim wrote:
    You can also generate a path builder class so you can
    do the same thing for related objects too. For example:

    Artist.NAME.eq("Picasso") // equals
    Artist.DATE_OF_BIRTH.lt(now()) // less than
    Having to repeat Artist. all over the place is exactly what I'd like to
    get rid of.
    Hmm...
    ...
    ... I see it's hard to see whether that's actually a problem or not.
    I see myself arguing on matters of principle, which is nice but risks
    failure when confronted with reality.
    I also see John arguing with small examples, which is nice but risks
    failure when trying to scale to complicated queries.
    How about if everybody with an interest in the topic scour their projects
    for the nastiest SQL that they have, and present them here?
    We'd have a set of use cases that will really test the various approaches.

    Regards
    Jo
  • Durchholz, Joachim at Feb 1, 2012 at 9:31 am

    Well, if your code is well designed your artist fetch logic is
    probably in the Artist class
    Many queries aren't really "artist fetch logic" but ad-hoc statistics stuff. The kind of query with aggregate functions.
    A query DSL should be built for ad-hoc queries anyway. Fetching the data model from the database is already covered at the entity bean layer, tailoring the DSL for the ad-hoc queries is going to gain Cayenne more new power than tailoring it for predesigned fetch logic.

    Besides, the argument loses some weight as soon as subqueries and joins come into play.
    You could move those parts of the query to the other class, but you'd have to wrap each snippet that you move in a function, give it a name, and call it from the main class. Might give you a better design, or might be hopelessly overengineered.
    so the class name isn't needed.
    If you are doing something inside the class you can use a
    static import to move all the artist stuff into the
    namespace and then use it without qualification.
    'Artist.' would be the lesser evil when it comes to quick coding, as it can leverage code completion (static imports can't because the list of potential matches would be huge).

    Regards,
    Jo
  • Aristedes Maniatis at Jan 28, 2012 at 9:39 am

    On 28/01/12 12:51 AM, Andrus Adamchik wrote:
    My only quibble with order() is it sounds immediate. Maybe orderBy()
    instead?
    Fine with me.
    For fetch limits, could have a limitTo() method?
    FetchLimit is a bit different - it a "property" in a Java beans sense. The ordering API changes do not affect the "property" aspect of it. So what is the goal here, to provide chainable API?
    Personally I like it. I think I mentioned Ruby/Rails before, and their chainable query API is very succinct and readable. Now Java is naturally more verbose than Ruby as a language, but I like the sort of chainable api that looks something like this:

    List artists<Artist> = SelectQuery(Artist.class).where("name LIKE 'b%').and('age > 23').join(Gallery.class).limit(10).order(Artist.name).perform();

    We've had this conversation before, and I guess it really needs one of us to write up the full class API for what this sort of approach would look like if it is ever going to get past these conversations. I'd love if I had more time to sit down and think about this, but realistically that isn't soon.

    Regards

    Ari


    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
  • Andrus Adamchik at Jan 30, 2012 at 7:35 am
    I am glad that the API evolution doesn't stop and is not waiting for this or that "big thing" to happen. The new ordering methods might become available before we take our time to design the new query. The new vararg/generics ObjectContext methods are already available, even though we haven't figured out generic queries yet, etc. This makes Cayenne better now and not later.

    But at some point we'll have to take on that big thing - a generics-friendly selecting query combining features of EJBQLQuery and SelectQuery, that can be created from String or via API, with API being chainable.

    For me - I need to finish 3.1 docs and release 3.1... I'd think we can do it in 3.2 then.

    Andrus

    On Jan 28, 2012, at 12:38 PM, Aristedes Maniatis wrote:
    On 28/01/12 12:51 AM, Andrus Adamchik wrote:
    My only quibble with order() is it sounds immediate. Maybe orderBy()
    instead?
    Fine with me.
    For fetch limits, could have a limitTo() method?
    FetchLimit is a bit different - it a "property" in a Java beans sense. The ordering API changes do not affect the "property" aspect of it. So what is the goal here, to provide chainable API?
    Personally I like it. I think I mentioned Ruby/Rails before, and their chainable query API is very succinct and readable. Now Java is naturally more verbose than Ruby as a language, but I like the sort of chainable api that looks something like this:

    List artists<Artist> = SelectQuery(Artist.class).where("name LIKE 'b%').and('age > 23').join(Gallery.class).limit(10).order(Artist.name).perform();

    We've had this conversation before, and I guess it really needs one of us to write up the full class API for what this sort of approach would look like if it is ever going to get past these conversations. I'd love if I had more time to sit down and think about this, but realistically that isn't soon.

    Regards

    Ari

    --
    -------------------------->
    Aristedes Maniatis
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupdev @
categoriescayenne
postedJan 26, '12 at 5:16p
activeFeb 1, '12 at 9:31a
posts22
users6
websitecayenne.apache.org

People

Translate

site design / logo © 2021 Grokbase