Re: performQuery generics

From: Aristedes Maniatis (ar..sh.com.au)
Date: Thu Dec 27 2007 - 03:50:53 EST

  • Next message: Aristedes Maniatis: "Re: performQuery generics"

    On 27/12/2007, at 1:29 AM, Mike Kienenberger wrote:

    > String pathSpec = Artist.ARTIST_NAME_PROPERTY;
    > or
    > String pathSpec = Painting.ARTIST_PROPERTY + "." +
    > Artist.ARTIST_NAME_PROPERTY;
    >
    > Note also, that the pastSpec has the same suffix -- all you need to do
    > is adjust the prefix to account for a different root:

    But that is exactly my point: the Expression object is different
    depending on where the root of the query starts. Sure the end part of
    the expression is the same, but that doesn't help anyone reuse an
    Expression object and so it is intrinsically tied to a root entity.

    Andrus's point is that they can be reused if you happen to name your
    properties the same between multiple entities, but the thought hadn't
    even occurred to me that this would be useful - I'd consider it poor
    practice to make these sorts of assumptions about the model. Someone
    could change the model and break a whole lot of code without a single
    compile time exception.

    Expression e = ExpressionFactory.matchExp(Painting.NAME_PROPERTY,
    "bob");

    Sure, the Painting.NAME_PROPERTY and Artist.NAME_PROPERTY might both
    be equal("name") and the above expression will work for both artists
    called bob and paintings called bob. But does anyone actually use
    Cayenne like this? What happens when someone changes
    Artist.NAME_PROPERTY to Artist.LASTNAME_PROPERTY?

    Could it then make sense to do this:

    1. Expression<Artist> e =
    ExpressionFactory.matchExp(Artist.NAME_PROPERTY, "bob", Artist.class);
    2. e = e.andExpr(ExpressionFactory.matchExp(Artist.SUBURB_PROPERTY,
    "Newtown", Artist.class));
    3. e = e.andExpr(ExpressionFactory.matchExp(Artist.STATE_PROPERTY,
    "NSW")); <--- no compile time checking here
    4. e = e.andExpr(ExpressionFactory.matchExp(Artist.NAME_PROPERTY,
    "bob", Painting.class)); <--- oops, error here

    The benefits:

    * when combining expressions (eg. andExp) type safety can be enforced
    at compile time (if the root class is passed for each expression which
    makes up the whole)
    * the root entity class can flow through to query without needing to
    be passed again: simpler, cleaner API. Expression and Query get
    generified together.
    * works like EJBQL which people will probably get to know over time

    The cons:

    * can't use the trick of sharing expressions across properties with
    identical names from several entities
    * something makes me think that line 3 may run into problems with
    generics internal to Cayenne code and we will not be able to force the
    cast of <?> into <Artist>. But I remain hopeful that there is a way,
    and even if not it doesn't kill the idea, just make it more awkward to
    use when building long compound expressions.
    * significant change to the previous API (but if we are going to force
    people to make a change, better that it be done as best we can right
    now)

    I know this is just half the problem (the other half is how to decide
    whether you are getting datarows or some other type back from a
    query), so I just throw this up as an idea. To my mind it is the
    philosophically appropriate place to inject the root entity.

    Ari Maniatis

    -------------------------->
    ish
    http://www.ish.com.au
    Level 1, 30 Wilson Street Newtown 2042 Australia
    phone +61 2 9550 5001 fax +61 2 9550 4001
    GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A



    This archive was generated by hypermail 2.0.0 : Thu Dec 27 2007 - 03:51:41 EST