11.3. JDOQL
Prev | Chapter 11. Query | Next

## 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:

- Equality and ordering comparisons between primitives and instances of wrapper classes (`Boolean, Byte, Integer`, etc) are valid.

- Equality and ordering between `Date`s 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 ();

Prev | Up | Next
11.2. Optional Query Elements | Home | 11.4. Executing Queries