You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cayenne.apache.org by Andrus Adamchik <an...@objectstyle.org> on 2007/12/27 11:53:12 UTC

ExpressionFactory -> ExpressionBuilder [Was: performQuery generics]

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
>
>
>


Typesafe property declarations [Was: ExpressionFactory -> ExpressionBuilder [Was: performQuery generics]]

Posted by Andrus Adamchik <an...@objectstyle.org>.
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
>>
>>
>>
>
>