JDOQL is a data store-neutral query language based on Java boolean expressions. The syntax of JDOQL is the same as standard Java syntax, with the following exceptions:
Equality and ordering comparisons between primitives and instances of wrapper classes (Boolean, Byte, Integer, etc) are valid.
Equality and ordering between Dates are valid.
Equality comparisons always use the == operator; the equals method is not supported.
The assignment operators (=, +=, *=, etc) and ++ and -- operators are not supported.
Methods are not supported, with the following exceptions:
Collection.contains
Collection.isEmpty
String.startsWith
String.endsWith
Traversing a null-valued field, which would normally throw a NullPointerException, instead causes the subexpression to evaluate to false for the current candidate.
The following literal types are supported: character literals, integer literals, floating point literals, boolean literals, string literals, and the null literal.
![]() | Note |
---|---|
Kodo JDO offers several extensions to JDOQL, and allows you to define your own extension as well. See the user guide for details. |
We will now present several examples illustrating the features of JDOQL and the Query interface. The examples use the following persistence-capable classes:
package org.mag; public class Magazine { private String title; private double price; private int copiesSold; private Company publisher; private Article coverArticle; private Set articles; ... } public class Article { private String title; private Collection subTitles; ... } package org.mag.pub; public class Company { private String name; private double revenue; ... }
Example 11.1. Basic Query
Find all magazines whose price is greater than 10 dollars. Notice that we can use the candidate class' persistent fields in our filter string. JDOQL is based only on the object model, not on the underlying data store representation of the object.
Extent mags = pm.getExtent (Magazine.class, false); String filter = "price > 10.0"; Query query = pm.newQuery (mags, filter); Collection results = (Collection) query.execute ();
Example 11.2. Result Ordering and Method Calls
Find all magazines whose title starts with "The ", in ascending order by price.
Extent mags = pm.getExtent (Magazine.class, false); String filter = "title.startsWith (\"The \")"; Query query = pm.newQuery (mags, filter); query.setOrdering ("price ascending"); Collection results = (Collection) query.execute ();
Example 11.3. Mathematical Operations and Relation Traversal
Find all magazines whose sales account for over 1% of the total revenue for the publisher, in descending order by publisher revenue and ascending order by publisher name. Notice the use of standard "dot" syntax to traverse into the magazine's publisher relation to retrieve the revenue and name fields.
Extent mags = pm.getExtent (Magazine.class, false); String filter = "price * copiesSold > publisher.revenue * .01"; Query query = pm.newQuery (mags, filter); query.setOrdering ("publisher.revenue descending, publisher.name ascending"); Collection results = (Collection) query.execute ();
Example 11.4. Precedence and Logical Operators
Find all magazines published by Random House or Addison Wesley whose price is less than or equal to 10 dollars.
Extent mags = pm.getExtent (Magazine.class, false); String filter = "price <= 10.0 " + "&& (publisher.name == \"Random House\" " + "|| publisher.name == \"Addison Wesley\")"; Query query = pm.newQuery (mags, filter); Collection results = (Collection) query.execute ();
Example 11.5. Imports and Parameters
Find all magazines published by a given company whose price is greater than a given number. Notice that both the company and the number to use are represented by placeholder parameters in the filter string; their values are not supplied until the query is executed. We import the org.mag.pub package classes so that we can declare a parameter of type Company, which resides in that package. We could just as easily skipped the import and declared the parameter using the fully-qualified org.mag.pub.Company type. Importing or full qualification is only necessary when the declared class is not in java.lang, java.util, java.match, or the package of the query's candidate class.
Company myCompany = ...; Double myPrice = ...; Extent mags = pm.getExtent (Magazine.class, false); String filter = "publisher == pub && price > amnt"; Query query = pm.newQuery (mags, filter); query.declareImports ("import org.mag.pub.*;"); query.declareParameters ("Company pub, Double amnt"); Collection results = (Collection) query.execute (myCompany, myPrice);
Example 11.6. Collections
Find all magazines whose cover article has a subtitle of "The Real Story" or whose cover article has no subtitles.
Extent mags = pm.getExtent (Magazine.class, false); String filter = "coverArticle.subTitles.contains (\"The Real Story\") " + "|| coverArticle.subTitles.isEmpty ()"; Query query = pm.newQuery (mags, filter); Collection results = (Collection) query.execute ();
Example 11.7. Variables
Find all magazines that have an article titled "Fourier Transforms". Notice the use of a variable to represent any article in the magazine's articles collection.
Extent mags = pm.getExtent (Magazine.class, false); String filter = "articles.contains (art) " + "&& art.title == \"Fourier Transforms\""; Query query = pm.newQuery (mags, filter); query.declareVariables ("Article art"); Collection results = (Collection) query.execute ();
Example 11.8. Collection Parameters
Find all magazines that have an article whose title is one of a number of passed-in possibilities. Here, we use a collection parameter to hold all the possible values. If you are familiar with SQL, this is JDOQL's equivalent to the SQL IN test.
Collection titles = ...; // collection of possible titles Extent mags = pm.getExtent (Magazine.class, false); String filter = "articles.contains (art) " + "&& titles.contains (art.title)"; Query query = pm.newQuery (mags, filter); query.declareParameters ("Collection titles"); query.declareVariables ("Article art"); Collection results = (Collection) query.execute ();