From: Aristedes Maniatis
Sent: Monday, January 30, 2012 12:21 PM
Subject: Re: SelectQuery + Orderings
On 30/01/12 9:12 PM, Durchholz, Joachim wrote:
new QualifierList ()
new Greater("age", 23)
I am not sure you have achieved any more readability over the plain string version.
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):
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:
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.conditions() // FAIL
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:
.end() // redundant
.end() // redundant
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 :-)