On 8/1/17 1:03am, Nikita Timofeev wrote: > The later is closer to the design. > Both column() and columns() methods return same ObjectSelect object, > they only change result type (as fetchDataRows() method do): > column() changes result to ObjectSelect<T>, where T is type of > Property, so no cast of the result required > and columns() changes to ObjectSelect<Object[]>. The idea is that you > can still use all methods in ObjectSelect.
Yes, fair enough and that makes sense. So could we do this: List<Object[]> namesAndBirthDates = ObjectSelect.query(Artist.class) .column(Artist.ARTIST_NAME) .column(Artist.ARTIST_BIRTH_DATE) .select(context); how can we handle the result type? Will this work with selectOne() returning Object or Object[] in difference cases? > Property<Integer> nameLength = > Property.create(FunctionExpressionFactory.lengthExp(Artist.ARTIST_NAME.path()), > Integer.class); > List<Artist> artists = ObjectSelect.query(Artist.class) > .where(nameLength.gt(10)) > .select(context); Could that syntax above could be cleaner like: Property<Integer> nameLength = Artist.ARTIST_NAME.function(Expression.SQL_LENGTH) or is that just going to result in a whole lot of clutter in the class? >> I know factories are the Java way, but given how common count() and max() >> are, surely we'd want a shortcut. I'd like to be able to go directly to: >> >> int count = ObjectSelect.query(Artist.class) >> .where(Artist.ARTIST_NAME.eq("Ari")) >> .selectCount(context); >> > I want this shortcut too :) I'd like to avoid a feature bloat, so that > could be done later. I think its worth planning the API for this now, given that this is probably the most common function used. I was trying to think of some syntax using Java 8 lambas, but couldn't quite see how it might work cleanly. >> would a map be more useful to return than this tuple style approach? Java's >> collections are a bit clunky, but: >> >> >> Map<PersistentObject, Object[]> result2 = ObjectSelect.query(Artist.class) >> .columns(Artist.ARTIST_NAME, paintingCountProperty) >> .having(paintingCountProperty.gt(10L)) >> .select(context); >> > I'm not sure that Map<> will be a good approach to the problem. > We actually discussed with Andrus how PersistentObject can be returned > with columns() method. > And we decided that it will be better to define explicitly that you > want PersistentObject in result: > > Property<Artist> artistSelf = Property.create("hollowArtist", ?some > expression?, Artist.class); > List<Object[]> result2 = ObjectSelect.query(Artist.class) > .columns(Artist.ARTIST_NAME, artistSelf, > paintingCountProperty) > .having(paintingCountProperty.gt(10L)) > .select(context); > > What do you think about it? Seems reasonable. Given this could be a very useful approach, it makes sense to make the syntax above a it more explicit or simple. List<Object[]> result2 = ObjectSelect.query(Artist.class) .columns(Artist.ARTIST_NAME, Property.HOLLOW_OBJECT, paintingCountProperty) .having(paintingCountProperty.gt(10L)) .select(context); This sort of query would be great for displaying a list of records (where you might want only a couple of columns to be loaded and displayed rather than whole objects). But then double clicking opens an edit view and you want to easily fault all its attributes without worrying about tracking its PK directly. Finally, 'having()' matches the SQL (HAVING is needed for queries on the result of functions). Have you thought about how that could be abstracted away so that the user can use where() and the correct SQL is still generated by Cayenne? Ari -- --------------------------> Aristedes Maniatis GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A