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.
Note | |
---|---|
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>] [variables <variable declarations>] [parameters <parameter declarations>] [<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 ();