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);
+    @SuppressWarnings("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


Reply via email to