11.2. JDOQL
Prev | Chapter 11. Query | Next

## 11.2. JDOQL

JDOQL is a datastore-neutral query language based on Java. It relies solely on your object model, completely abstracting the details of the underlying data model. As you have already seen, the syntax of JDOQL is virtually identical to Java syntax. In fact, a good trick when writing a JDOQL string is to pretend that you are writing a method of the query's candidate class. You have access to all of the class' persistent fields, and to the `this` keyword. There are, however, some notable ways in which JDOQL differs from Java:

- You can traverse through private persistent fields of relations.

- String literals can be either double-quoted or single-quoted.

- 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) as well as the `++` and `--` operators are not supported.

- Methods are not supported, with the following exceptions:

  - `Collection.contains`

  - `Collection.isEmpty`

  - `Map.containsKey`

  - `Map.containsValue`

  - `Map.isEmpty`

  - `String.toUpperCase`

  - `String.toLowerCase`

  - `String.startsWith`

  - `String.endsWith`

  - `String.matches`: Regular expression support is limited to the use of `.`, `.*`, and `(?i)` to represent case-insensitive matching.

  - `String.indexOf`: Both forms are supported.

  - `String.substring` : Both forms are supported.

  - `Math.abs`

  - `Math.sqrt`

  - `JDOHelper.getObjectId`

- JDOQL supports the following aggregates: `min, max, sum, avg, count`. We discuss aggregates in detail later in the chapter.

- Traversing a null-valued field causes the subexpression to evaluate to `false` rather than throwing a `NullPointerException`.

| Note
Bold items represent JDO 2's additions to JDOQL. Kodo also offers several proprietary extensions to JDOQL, and allows you to define your own extensions. See the Reference Guide Section 10.7, “Query Extensions” and Section 13.3, “JDOQL Subqueries” for details.

While is important to note the differences between JDOQL and Java enumerated in the list above, it is just as important to note what is not in the list. Mathematical operators, logical operators, `instanceof`, casting, field traversal, and static field access are omitted, meaning they are all fully supported by JDOQL.

We demonstrate some of the interesting aspects of JDOQL below.

Example 11.2. Relation Traversal and Mathematical Operations

Find all magazines whose sales account for over 1% of the total revenue for the publisher. Notice the use of standard Java "dot" notation to traverse into the persistent fields of `Magazine`'s `publisher` relation.

    Query query = pm.newQuery (Magazine.class,
        "price * copiesSold > publisher.revenue * .01");
    Collection mags = (Collection) query.execute ();

Example 11.3. Precedence, Logical Operators, and String Functions

Find all magazines whose publisher's name is "Random House" or matches a regular expression, and whose price is less than or equal to 10 dollars. Here, we use single-quoted string literals to avoid having to escape double quotes within the filter string. Notice also that we compare strings with `==` rather than the `equals` method.

    Query query = pm.newQuery (Magazine.class, "price <= 10.0 "
        + "&& (publisher.name == 'Random House' "
        + "|| publisher.name.toLowerCase ().matches ('add.*ley')");
    Collection mags = (Collection) query.execute ();

Example 11.4. Collections

Find all magazines whose cover article has a subtitle of "The Real Story" or whose cover article has no subtitles.

    Query query = pm.newQuery (Magazine.class,
        "coverArticle.subtitles.contains ('The Real Story') "
        + "|| coverArticle.subtitles.isEmpty ()";
    Collection mags = (Collection) query.execute ();

Example 11.5. Static Methods

Retrieve all magazines whose publisher's revenue's square root is greater than 100 dollars.

    Query query = pm.newQuery (Magazine.class,
        "Math.sqrt (publisher.revenue) > 100");
    Collection mags = (Collection) query.execute ();

Prev | Up | Next
Chapter 11. Query | Home | 11.3. Advanced Object Filtering