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 the
String.indexOf(String str)
and the
String.indexOf(String str, int fromIndex)
forms are supported.
String.substring
*:
Both the
String.substring(int start)
and the
String.substring(int beingIndex, int endIndex)
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 | |
---|---|
Kodo offers several extensions to JDOQL, and allows you to define your own extensions. See the Reference Guide's Section 9.6, “Query Language Extensions” and Section 9.6.4, “JDOQL Subqueries” for details. |
While it 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"); List mags = (List) 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')"); List mags = (List) 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 ()"; List mags = (List) query.execute ();