Re: performQuery generics

From: Andrus Adamchik (andru..bjectstyle.org)
Date: Wed Dec 26 2007 - 05:49:59 EST

  • Next message: Mike Kienenberger: "Re: performQuery generics"

    On Dec 26, 2007, at 4:14 AM, Aristedes Maniatis wrote:

    >
    > On 25/12/2007, at 2:20 AM, Andrus Adamchik wrote:
    >
    >> - List<?> performQuery(Query query);
    >> + ..uppressWarnings("unchecked")
    >> + List performQuery(Query query);
    >>
    >
    > I agree. Returning <?> from a function call does nothing for type
    > safety at all, so it may as well not be there. Pretty much everwhere
    > we return <?> from a function should be considered suspect and some
    > of the places <Object> can be found are also candidates for
    > refactoring.

    Will go ahead with this change.

    > On 22/12/2007, at 2:53 AM, Andrus Adamchik wrote:
    >
    >> The wrapper idea (SelectBuilder) is sort of along the lines of
    >> reversing the API that you suggested. But let me comment on why I
    >> am not a fan of adding new ways to run a query to the
    >> ObjectContext. When implementing ROP and nested contexts I found
    >> out that having so many "redundant" or "utility" methods in a
    >> context object makes it extremely hard to implement multi-layer
    >> contexts. So I'd prefer that we keep ObjectContext API as lean as
    >> possible, and pass all query parameters in the query object itself.
    >
    > What we are discussing comes down to whether the query type
    > (datarows or persistent objects) should be injected into the Query
    > as part of the constructor (as per your new SelectBuilder or Tore's
    > subclass idea), sometime after (as per the existing Query) or when
    > you want the query executed (as per my idea with multiple return
    > functions).

    IMO this is a rather accurate analysis.

    > List<Artists> result = query.getResult(Artist.class, context);
    > Map<String, Artists> result = query.getResultAsMap(Artist.class,
    > context, NAME_PROPERTY);
    > List<DataRow> result = query.getResultAsDataRows(Artist.class,
    > context);

    Since Query interface is another core Cayenne abstraction, adding
    utility methods to it is causing a similar ripple effect as adding
    them to ObjectContext... E.g. a DeleteBatchQuery would now have a
    'getResult' method... Also we'd have to add update methods returning
    update counts, select methods returning Object[] (something we are
    implementing now per JPA), etc... In other words, too many loose ends.

    So, weighing all options, I think we can make a bit of a concession on
    the ObjectContext expansion, to provide minimally generics-friendly
    API without changing how Cayenne works, and move all utilities (such
    as getResultAsMap fetch) to the new Builders:

         // existing
         List performQuery(Query query);

         // existing
         QueryResponse performGenericQuery(Query query);

         // new
         <T> List<T> performQuery(Class<T> aClass, Query query);

         // new
         List<DataRow> performDataRowQuery(Query query);

    It still makes things a bit more verbose (and redundant, as Class will
    be specified twice - once in query constructor, and second time in the
    context), but everything about generics is verbose and redundant after
    all :-/ I guess after that we can deprecate 'setDataRows' on
    SelectQuery and SQLTemplate, (as well as
    "ObjectContext.performQuery(Query)", although we can keep this one
    around longer as it is heavily used by everybody).

    Hmm... actually this would allow us to make Class argument optional in
    the constructor of SelectQuery, and SQLTemplate, that most often than
    not fetches DataRows anyways.

    I need to do more analysis how the new JPA related result sets will
    play with this... But what is everyone's feeling on that? Seems like
    the least invasive change to me....

    > I have to confess to not quite understanding the boundaries between
    > Expression and Query. 99% of the times that it is used, a Query is
    > just an Expression with Ordering and a root entity.

    Yes, Expression is a qualifier *part* of the SelectQuery.

    > But I don't understand why that root entity isn't part of the
    > Expression itself - does an expression have much meaning without a
    > root entity? It is always implied within the Expression, since you
    > can't create an expression which is meaningful for Artist.class and
    > then create a new SelectQuery(Painting.class).

    Coincidentally, since Expressions are not bound to a java class, you
    can use the same expression with a group of classes that do not
    inherit from each other, but simply share property names. I think of
    that as a nice side effect. The design idea is that a SelectQuery is a
    composition of the parts, Expression being one of them.

    Andrus



    This archive was generated by hypermail 2.0.0 : Wed Dec 26 2007 - 05:50:34 EST