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 2009/12/30 22:54:08 UTC

Re: Type-safe qualifiers (and queries)

On Dec 30, 2009, at 9:59 PM, Andrus Adamchik wrote:

> I'd like to see if a similar approach can be extended to query  
> building. Although that'll be a entirely different level of effort.

Or maybe it is not that hopeless and we can use a set of user-facing  
query "builders" without affecting our backend implementations. Just  
prototyped a builder that can create EJBQL/SelectQuery with  
parameterized result type that can be tied to  
ObjectContext.performQuery()...

public interface Query<T> ...
public class Select<T> implements Query<T>...

Here is now we can build correctly parameterized queries for different  
result types. Also shows other EJBQL features, like subqueries. While  
it adds some more terse API compared to SelectQuery, parameterization  
is the main point here. I guess this is a good way to make EJBQLQuery  
finally usable:

void query_newAPI_EntityResult() {

	Select<Artist> query = Select.entity(Artist.class);
	query.setDistinct();

	Select<Painting> subquery = Select.entity(Painting.class);
	subquery.setWhere(Painting.NAME.like("X%"));

	Expression clause1 = Artist.NAME.eq("X");
	Expression clause2 = Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
	Expression clause3 = Exists.in(subquery);
	query.setWhere(All.of(clause1, clause2, clause3));

	query.addOrderByAscending(Artist.NAME);
	query.addOrderByAscending(Artist.PAINTINGS.dot(Painting.NAME));

	query.addDisjointPrefetch(Artist.PAINTINGS);
}

void query_newAPI_ScalarResult() {

	Select<Date> query = Select.scalar(Artist.class, Artist.DATE_OF_BIRTH);

	Expression clause1 = Artist.NAME.eq("X");
	Expression clause2 = Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
	query.setWhere(Any.of(clause1, clause2));
}

void query_newAPI_MixedResult() {

	// fetching Artist entity plus paintings count
	Select<Object[]> query = Select.mixed(Artist.class,
			new Key<Artist>(""), Artist.PAINTINGS.count());

	Expression clause1 = Artist.NAME.eq("X");
	Expression clause2 = Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
	query.setWhere(Any.of(clause1, clause2));
}

void query_newAPI_GenericObject() {

	Select<Persistent> query = Select.generic(Persistent.class,
			"MyGenericEntity");

	Expression clause1 = new Key<String>("name").eq("X");
	Expression clause2 = new Key<Integer>("age").eq(5);
	query.setWhere(All.of(clause1, clause2));
}

void query_newAPI_DataRow() {

	Select<DataRow> query = Select.dataRow(Artist.class);

	Expression clause1 = Artist.NAME.eq("X");
	Expression clause2 = Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
	query.setWhere(All.of(clause1, clause2));
}



Andrus

Re: Type-safe qualifiers (and queries)

Posted by Andrus Adamchik <an...@objectstyle.org>.
Yeah, seems like the same thing, but not parameterized properly.

Andrus

On Dec 31, 2009, at 6:38 AM, Mike Kienenberger wrote:

> Maybe worth imitating how JPA 2.0 does it?  I've only glanced at it in
> the past, but it seems similar.  (Eclipselink is the reference
> implementation.)
>
> http://wiki.eclipse.org/Introduction_to_EclipseLink_Expressions_%28ELUG%29
>
> http://wiki.eclipse.org/EclipseLink/Examples/JPA/ORMQueries
>
> http://www.eclipse.org/eclipselink/api/1.1/org/eclipse/persistence/expressions/ExpressionBuilder.html
>
> There's also something called a Criteria api now in JPA 2.0.   I only
> looked at it (in the spec) as I was typing this message.
>
> http://jcp.org/aboutJava/communityprocess/pfd/jsr317/index2.html
> Chapter 6
>
> Not sure exactly how it's different -- maybe it's just a specification
> of the expression builder syntax.
>
>
>
> On Wed, Dec 30, 2009 at 4:54 PM, Andrus Adamchik <andrus@objectstyle.org 
> > wrote:
>>
>> On Dec 30, 2009, at 9:59 PM, Andrus Adamchik wrote:
>>
>>> I'd like to see if a similar approach can be extended to query  
>>> building.
>>> Although that'll be a entirely different level of effort.
>>
>> Or maybe it is not that hopeless and we can use a set of user- 
>> facing query
>> "builders" without affecting our backend implementations. Just  
>> prototyped a
>> builder that can create EJBQL/SelectQuery with parameterized result  
>> type
>> that can be tied to ObjectContext.performQuery()...
>>
>> public interface Query<T> ...
>> public class Select<T> implements Query<T>...
>>
>> Here is now we can build correctly parameterized queries for  
>> different
>> result types. Also shows other EJBQL features, like subqueries.  
>> While it
>> adds some more terse API compared to SelectQuery, parameterization  
>> is the
>> main point here. I guess this is a good way to make EJBQLQuery  
>> finally
>> usable:
>>
>> void query_newAPI_EntityResult() {
>>
>>        Select<Artist> query = Select.entity(Artist.class);
>>        query.setDistinct();
>>
>>        Select<Painting> subquery = Select.entity(Painting.class);
>>        subquery.setWhere(Painting.NAME.like("X%"));
>>
>>        Expression clause1 = Artist.NAME.eq("X");
>>        Expression clause2 =  
>> Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
>>        Expression clause3 = Exists.in(subquery);
>>        query.setWhere(All.of(clause1, clause2, clause3));
>>
>>        query.addOrderByAscending(Artist.NAME);
>>         
>> query.addOrderByAscending(Artist.PAINTINGS.dot(Painting.NAME));
>>
>>        query.addDisjointPrefetch(Artist.PAINTINGS);
>> }
>>
>> void query_newAPI_ScalarResult() {
>>
>>        Select<Date> query = Select.scalar(Artist.class,
>> Artist.DATE_OF_BIRTH);
>>
>>        Expression clause1 = Artist.NAME.eq("X");
>>        Expression clause2 =  
>> Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
>>        query.setWhere(Any.of(clause1, clause2));
>> }
>>
>> void query_newAPI_MixedResult() {
>>
>>        // fetching Artist entity plus paintings count
>>        Select<Object[]> query = Select.mixed(Artist.class,
>>                        new Key<Artist>(""),  
>> Artist.PAINTINGS.count());
>>
>>        Expression clause1 = Artist.NAME.eq("X");
>>        Expression clause2 =  
>> Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
>>        query.setWhere(Any.of(clause1, clause2));
>> }
>>
>> void query_newAPI_GenericObject() {
>>
>>        Select<Persistent> query = Select.generic(Persistent.class,
>>                        "MyGenericEntity");
>>
>>        Expression clause1 = new Key<String>("name").eq("X");
>>        Expression clause2 = new Key<Integer>("age").eq(5);
>>        query.setWhere(All.of(clause1, clause2));
>> }
>>
>> void query_newAPI_DataRow() {
>>
>>        Select<DataRow> query = Select.dataRow(Artist.class);
>>
>>        Expression clause1 = Artist.NAME.eq("X");
>>        Expression clause2 =  
>> Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
>>        query.setWhere(All.of(clause1, clause2));
>> }
>>
>>
>>
>> Andrus
>>
>


Re: Type-safe qualifiers (and queries)

Posted by Mike Kienenberger <mk...@gmail.com>.
Maybe worth imitating how JPA 2.0 does it?  I've only glanced at it in
the past, but it seems similar.  (Eclipselink is the reference
implementation.)

http://wiki.eclipse.org/Introduction_to_EclipseLink_Expressions_%28ELUG%29

http://wiki.eclipse.org/EclipseLink/Examples/JPA/ORMQueries

http://www.eclipse.org/eclipselink/api/1.1/org/eclipse/persistence/expressions/ExpressionBuilder.html

There's also something called a Criteria api now in JPA 2.0.   I only
looked at it (in the spec) as I was typing this message.

http://jcp.org/aboutJava/communityprocess/pfd/jsr317/index2.html
Chapter 6

Not sure exactly how it's different -- maybe it's just a specification
of the expression builder syntax.



On Wed, Dec 30, 2009 at 4:54 PM, Andrus Adamchik <an...@objectstyle.org> wrote:
>
> On Dec 30, 2009, at 9:59 PM, Andrus Adamchik wrote:
>
>> I'd like to see if a similar approach can be extended to query building.
>> Although that'll be a entirely different level of effort.
>
> Or maybe it is not that hopeless and we can use a set of user-facing query
> "builders" without affecting our backend implementations. Just prototyped a
> builder that can create EJBQL/SelectQuery with parameterized result type
> that can be tied to ObjectContext.performQuery()...
>
> public interface Query<T> ...
> public class Select<T> implements Query<T>...
>
> Here is now we can build correctly parameterized queries for different
> result types. Also shows other EJBQL features, like subqueries. While it
> adds some more terse API compared to SelectQuery, parameterization is the
> main point here. I guess this is a good way to make EJBQLQuery finally
> usable:
>
> void query_newAPI_EntityResult() {
>
>        Select<Artist> query = Select.entity(Artist.class);
>        query.setDistinct();
>
>        Select<Painting> subquery = Select.entity(Painting.class);
>        subquery.setWhere(Painting.NAME.like("X%"));
>
>        Expression clause1 = Artist.NAME.eq("X");
>        Expression clause2 = Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
>        Expression clause3 = Exists.in(subquery);
>        query.setWhere(All.of(clause1, clause2, clause3));
>
>        query.addOrderByAscending(Artist.NAME);
>        query.addOrderByAscending(Artist.PAINTINGS.dot(Painting.NAME));
>
>        query.addDisjointPrefetch(Artist.PAINTINGS);
> }
>
> void query_newAPI_ScalarResult() {
>
>        Select<Date> query = Select.scalar(Artist.class,
> Artist.DATE_OF_BIRTH);
>
>        Expression clause1 = Artist.NAME.eq("X");
>        Expression clause2 = Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
>        query.setWhere(Any.of(clause1, clause2));
> }
>
> void query_newAPI_MixedResult() {
>
>        // fetching Artist entity plus paintings count
>        Select<Object[]> query = Select.mixed(Artist.class,
>                        new Key<Artist>(""), Artist.PAINTINGS.count());
>
>        Expression clause1 = Artist.NAME.eq("X");
>        Expression clause2 = Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
>        query.setWhere(Any.of(clause1, clause2));
> }
>
> void query_newAPI_GenericObject() {
>
>        Select<Persistent> query = Select.generic(Persistent.class,
>                        "MyGenericEntity");
>
>        Expression clause1 = new Key<String>("name").eq("X");
>        Expression clause2 = new Key<Integer>("age").eq(5);
>        query.setWhere(All.of(clause1, clause2));
> }
>
> void query_newAPI_DataRow() {
>
>        Select<DataRow> query = Select.dataRow(Artist.class);
>
>        Expression clause1 = Artist.NAME.eq("X");
>        Expression clause2 = Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
>        query.setWhere(All.of(clause1, clause2));
> }
>
>
>
> Andrus
>