JDO provides a flexible API for use of query languages. DataNucleus makes use of this to allow use
of the query language defined in the JPA1 specification (JPQL) with JDO persistence.
JPQL is a pseudo-OO language based around SQL, and so not using Java syntax, unlike JDOQL.
To provide a simple example, this is what you would do
Query q = pm.newQuery("javax.jdo.query.JPQL", "SELECT p FROM Person p WHERE p.lastName = 'Jones'");
List results = (List)q.execute();
This finds all "Person" objects with surname of "Jones". You specify all details in the query.
In traditional (declarative) JDOQL (JDO 1.0) it was necessary to specify the component parts
(filter, candidate class, ordering, etc) of the query using the mutator methods on the Query.
In JDO 2 you can now specify it all in a single string. This string has to follow a particular
pattern, but provides the convenience that many people have been asking for.
The pattern to use is as follows
[GROUP BY <grouping>]
[ORDER BY <ordering>]
The "keywords" in the query are shown in UPPER CASE are case-insensitive.
In the example shown you note that we did not specify the full class name. We used
and thereafter could refer to
as the alias. The
is called the
and in JPA MetaData this can be defined against each class in its definition.
With JDO we dont have this MetaData attribute so we simply define the
the name of the class omitting the package name
will have an entity name of
In JPQL queries it is convenient to pass in parameters so we dont have to define the same query
for different values. Let's take two examples
Named Parameters :
Query q = em.createQuery("SELECT p FROM Person p WHERE p.lastName = :surname AND o.firstName = :forename");
Numbered Parameters :
Query q = em.createQuery("SELECT p FROM Person p WHERE p.lastName = ?1 AND p.firstName = ?2");
So in the first case we have parameters that are prefixed by
(colon) to identify them as
a parameter and we use that name when calling
In the second case we have parameters that are prefixed by
(question mark) and are
numbered starting at 1. We then use the numbered position when calling
Sometimes you know that the query can only every return 0 or 1 objects. In this case you can
simplify your job by adding
In this case the return from the execution of the Query will be a single Object rather than a
List, so you've no need to use iterators, just cast it to your candidate class type.