11.3. JDOQL

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:

[Note]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, 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.declareImports ("import java.lang.*;");
query.declareParameters ("Collection titles");
query.declareVariables ("Article art");
Collection results = (Collection) query.execute (titles);