Sorry, the subject was wrong, as I started writing a message about something entirely different initially :-)

On Dec 27, 2007, at 12:53 PM, Andrus Adamchik wrote:

BTW, here is another data point for this discussion. Here is a type- safe bean framework written by one of the Cayenne users:

  http://ujoframework.pponec.net/

The framework itself has no direct relation to Cayenne, but I wonder if with proper code generation, we could use a similar approach of type-safe property declaration to achieve type safety in the ExpressionFactory methods. The fact that Cayenne doesn't tell you that you can't match say a String against a BigDecimal in an Expression has been causing some grief to our users already.

Andrus


On Dec 27, 2007, at 10:50 AM, Aristedes Maniatis wrote:
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






Reply via email to