11.9. Single-String JDOQL

It is often convenient to represent an entire JDOQL query as a single string. JDO defines a single-string query form that encompasses all parts of a query: the unique flag, result string, result class, filter, parameters, variables, imports, grouping, ordering, and range.


Kodo uses the single-string format to implement JDOQL subquery support, covered in Section 9.6.4, “JDOQL Subqueries” of the Reference Guide.

We present the grammar for single-string JDOQL queries below. Clauses in square brackets are optional. Clauses in angle brackets are required, and represent portions of the Query API.

select [unique] [<result>] [into <result class>]
    [from <candidate class> [exclude subclasses]]
    [where <filter>]
    [parameters <parameter declarations>]
    [variables <variable declarations>]
    [imports <import declarations>]
    [group by <grouping>]
    [order by <ordering>]
    [range <start>, <end>]

Each keyword above can appear in all lower case or all upper case.

The PersistenceManager has a factory method designed specifically for constructing a query from a JDOQL string:

public Query newQuery (String query);

Additionally, any of the PersistenceManager's query factory methods that accept a JDOQL filter string will also accept the JDOQL single-string format. See Section 8.11, “Query Factory”.

In each code block below, we create and execute a standard JDOQL query, then demonstrate the same process using the single-string format. As you'll see, translating any query into single-string form is just a matter of plugging the corresponding strings into the grammar above.

Query query = pm.newQuery ();
query.setResult ("distinct title");
query.setClass (Magazine.class);
query.setFilter ("price < :p");
query.setRange (10, 20);
List results = (List) query.execute (new Double (10.0));

Query query = pm.newQuery (Magazine.class, "select distinct title "
    + "where price < :p range 10, 20");
List results = (List) query.execute (new Double (10.0));
Query query = pm.newQuery ();
query.setUnique (true);
query.setCandidates (pm.getExtent (Magazine.class, false));
query.setFilter ("title == 'JDJ'");
Magazine mag = (Magazine) query.execute ();

Query query = pm.newQuery ("select unique from org.mag.Magazine "
    + "exclude subclasses where title == 'JDJ'");
Magazine mag = (Magazine) query.execute ();
Query query = pm.newQuery ();
query.setResult ("publisher.name as pub, avg(price) as price");
query.setResultClass (org.mag.pub.PubPrice.class);
query.setClass (Magazine.class);
query.setGrouping ("publisher having avg(price) < :p");
query.setOrdering ("publisher.name ascending");
query.setRange (3, Long.MAX_VALUE);
List results = (List) query.execute (new Double (10.0));

Query query = pm.newQuery ("select publisher.name as pub, avg(price) as price "
    + "into org.mag.pub.PubPrice from org.mag.Magazine "
    + "group by publisher having avg(price) < :p "
    + "order by publisher.name ascending range 3, Long.MAX_VALUE");
List results = (List) query.execute (new Double (10.0));

On a final note, single-string queries are mutable. You can construct a single-string query as in the examples above, then change the result string, filter, or any other part of the query through the standard Query APIs. This is especially useful for temporary properties like the result range, and for setting the candidate class:

Query query = pm.newQuery (Magazine.class, "select title where "
    + "title.startsWith ('J')");
query.setRange (10, 20);
Magazine mag = (Magazine) query.execute ();


Skip navigation bar   Back to Top