As shown earlier, there are two ways of defining the content of a query; using a single-string form, and using the API. Let's try to understand the Query API in JDO , We firstly need to look at a typical Query.

Query query = pm.newQuery(MyClass.class);
query.setFilter("field2 < threshold");
query.declareImports("import java.util.Date");
query.declareParameters("Date threshold");
query.setOrdering("field1 ascending");
List results = (List)query.execute(my_threshold);

In this Query, we create it to return objects of type mydomain.MyClass (or subclasses), and set the filter to restrict to instances of that type which have the field field2 less than some threshold value, which we don't know at that point. We've specified the query like this because we want to pass the threshold value in dynamically. We then import the type of our threshold parameter, and the parameter itself, and set the ordering of the results from the Query to be in ascending order of some field field1 . The Query is then executed, passing in the threshold value. The example is to highlight the typical methods specified for a Query. Clearly you may only specify the Query line if you wanted something very simple. The result of the Query is cast to a List since in this case it returns a List of results.

Let's review the methods of the JDO Query API. Not all methods apply to all query languages. The differences are noted in the sections below


Set the class of the candidate instances of the query. The class specifies the class of the candidates of the query. Elements of the candidate collection that are of the specified class are filtered before being put into the results.

This is applicable to JDOQL, SQL, JPQL.


Specify that only the first result of the query should be returned, rather than a collection. The execute method will return null if the query result size is 0.

This is applicable to JDOQL, SQL, JPQL.

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, so you've no need to use iterators, just cast it to your candidate class type.


Specifies what type of data this query should return. If this is unset or set to null, this query returns instances of the query's candidate class. If set, this query will return expressions, including field values (projections) and aggregate function results.

This is applicable to JDOQL.

The normal behaviour of JDOQL queries is to return a List of Objects of the type of the candidate class. Sometimes you want to have the query perform some processing and return things like count(), min(), max() etc. You specify this with

query.setResult("count(param1), max(param2), param3");

In this case the results will be List<Object[]> since there are more than 1 column in each row. If you have only 1 column in the results then the results would be List<Object>. If you have only aggregates (sum, avg, min, max, count) in the result clause then there will be only 1 row in the results and so the results will be of the form Object[] (or Object if only 1 aggregate). Please refer to JDOQL Result Clauses for more details.


Specify the type of object in which to return each element of the result of invoking execute(). If the result is not set or set to null, the result class defaults to the candidate class of the query. If the result consists of one expression, the result class defaults to the type of that expression. If the result consists of more than one expression, the result class defaults to Object[].

This is applicable to JDOQL, SQL.

When you perform a query, using JDOQL or SQL the query will, in general, return a List of objects. These objects are by default of the same type as the candidate class. This is good for the majority of situations but there are some situations where you would like to control the output object. This can be achieved by specifying the Result Class .


The Result Class has to meet certain requirements. These are

  • Can be one of Integer, Long, Short, Float, Double, Character, Byte, Boolean, String, java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp, or Object[]
  • Can be a user defined class, that has either a constructor taking arguments of the same type as those returned by the query (in the same order), or has a public put(Object, Object) method, or public setXXX() methods, or public fields.

Where you have a query returning a single field, you could specify the Result Class to be one of the first group for example. Where your query returns multiple fields then you can set the Result Class to be your own class. So we could have a query like this

Query query = pm.newQuery(pm.getExtent(Payment.class,false));
query.setFilter("amount > 10.0");
query.setResult("amount, currency");
List results = (List)query.execute();

and we define our Result Class Price as follows

public class Price
    protected double amount = 0.0;
    protected String currency = null;

    public Price(double amount, String currency)
        this.amount = amount;
        this.currency = currency;


In this case our query is returning 2 fields (a Double and a String), and these map onto the constructor arguments, so DataNucleus will create objects of the Price class using that constructor. We could have provided a class with public fields instead, or provided setXXX methods or a put method. They all work in the same way.


Set the range of results to return. The execution of the query is modified to return only a subset of results. If the filter would normally return 100 instances, and fromIncl is set to 50, and toExcl is set to 70, then the first 50 results that would have been returned are skipped, the next 20 results are returned and the remaining 30 results are ignored. An implementation should execute the query such that the range algorithm is done at the data store.

This is applicable to JDOQL.

Sometimes you have a Query that returns a large number of objects. You may want to just display a range of these to your user. In this case you can do

query.setRange(10, 20);

This has the effect of only returning items 10 through to 19 (inclusive) of the query's results. The clear use of this is where you have a web system and you're displaying paginated data, and so the user hits page down, so you get the next "n" results.

setRange is implemented efficiently for MySQL, Postgresql, HSQL (using the LIMIT SQL keyword) and Oracle (using the ROWNUM keyword), with the query only finding the objects required by the user directly in the datastore. For other RDBMS the query will retrieve all objects up to the "to" record, and will not pass any unnecessary objects that are before the "from" record.


Set the filter for the query. The filter specification is a String containing a Boolean expression that is to be evaluated for each of the instances in the candidate collection. If the filter is not specified, then it defaults to "true", which has the effect of filtering the input Collection only for class type.

This is applicable to JDOQL.


Set the import statements to be used to identify the fully qualified name of variables or parameters. Parameters and unbound variables might come from a different class from the candidate class, and the names need to be declared in an import statement to eliminate ambiguity. Import statements are specified as a String with semicolon-separated statements.

This is applicable to JDOQL.

In JDOQL you can declare parameters and variables. Just like in Java it is often convenient to just declare a variable as say Date, and then have an import in your Java file importing the java.util.Date class. The same applies in JDOQL. Where you have defined parameters or variables in shorthand form, you can specify their imports like this

query.declareVariables("Date startDate");
query.declareParameters("Locale myLocale");
query.declareImports("import java.util.Locale; import java.util.Date;");

Just like in Java, if you declare your parameters or variables in fully-specified form (for example "java.util.Date myDate") then you do not need any import.

The JDOQL uses the imports declaration to create a type namespace for the query. During query compilation, the classes used in the query, if not fully qualified, are searched in this namespace. The type namespace is built with the following:

  • primitives types
  • java.lang.* package
  • package of the candidate class
  • import declarations (if any)

To resolve a class, the JDOQL compiler will use the class fully qualified name to load it, but if the class is not fully qualified, it will search by prefixing the class name with the imported package names declared in the type namespace. All classes loaded by the query must be acessible by either the candidate class classloader, the PersistenceManager classloader or the current Thread classloader. The search algorithm for a class in the JDOQL compiler is the following:

  • if the class is fully qualified, load the class.
  • if the class is not fully qualified, iterate each package in the type namespace and try to load the class from that package. This is done until the class is loaded, or the type namespace package names are exausted. If the class cannot be loaded an exception is thrown.

Note that the search algorithm can be problematic in performance terms if the class is not fully qualified or declared in imports using package notation. To avoid such problems, either use fully qualified class names or import the class in the imports declaration. The 2 queries below are examples of good usage:

query.declareImports("import java.util.Locale;");
query.declareParameters("Locale myLocale");
query.declareParameters("java.util.Locale myLocale");

However, the below example will suffer in performance, due to the search algorithm.

query.declareImports("import java.math.*; import java.util.*;");
query.declareParameters("Locale myLocale");


Declare the list of parameters query execution. The parameter declaration is a String containing one or more query parameter declarations separated with commas. Each parameter named in the parameter declaration must be bound to a value when the query is executed.

This is applicable to JDOQL.

When specifying JDOQL queries you can use normal Java classes in the query. You need to define to JDOQL which class you are talking about. You can do this via the following calls

query.declareImports("import mypackage.myclass; import mypackage2.*");
query.declareParameters("String myparam1, Date myparam2");

This tells JDO (and more specifically DataNucleus) to look for any classes specified as parameters, in the defined list of imports. java.lang is imported automatically here so you don't need to specify this. It should be noted that if you specify a package in the imports (using * notation), then DataNucleus will have to search for your class in that package and this can have a (small) performance impact. You can get around this by not using "*" notation on imports. What are shown above are called explicit parameters .

In JDO2 you can alternatively utilise implicit parameters . This is done by specifying the parameter name in the query directly (prefixed by a colon). So you may write a Single-String query like

Query query = pm.newQuery("SELECT FROM mydomain.Product WHERE price < :limit");
List results = (List)query.execute(new Double(200.0));

Here we haven't declared the parameter. We simply prefixed it with a colon, and its type will be determined implicitly from the query.

In some situations you may have a map of parameters keyed by their name, yet the query in question doesn't need all parameters. Normal JDO execution would throw an exception here since they are inconsistent with the query. You can omit this check by setting

q.addExtension("datanucleus.query.ignoreParameterCountCheck", "true");


Declare the unbound variables to be used in the query. Variables might be used in the filter, and these variables must be declared with their type. The unbound variable declaration is a String containing one or more unbound variable declarations separated with semicolons.

This is applicable to JDOQL.

In JDOQL you can connect two parts of a query using something known as a variable. For example, we want to retrieve all objects with a collection that contains a particular element, and where the element has a particular field value. We define a query like this

Query query = pm.newQuery(
    "SELECT FROM mydomain.Supplier WHERE products.contains(prod) && prod.name == \"Beans\"");

So we have a variable in our query called "prod" that connects the two parts. We now declare it

query.declareVariables("mydomain.Product prod");

This is known as an explicit variable , since it is declared explicitly. Multiple variables can be declared using semi-colon ( ; ) to separate variable declarations.

query.declareVariables("String var1; String var2");

JDO2 also defines implicit variables , where we skip the declareVariables call and rely on the JDO implementation to work out the type of the variable.


Set the candidate Collection to query. Used where you have some instances and want to know which pass a specified filter. This will result in the query being performed in-memory rather than in the datastore. [Note that in legacy JDOQL/JPQL implementations for RDBMS this will still go to the datastore].

This is applicable to JDOQL.


Set the ordering specification for the result Collection. The ordering specification is a String containing one or more ordering declarations separated by commas. Each ordering declaration is the name of the field on which to order the results followed by one of the following words: "ascending" or "descending". The field must be declared in the candidate class or must be a navigation expression starting with a field in the candidate class.

This is applicable to JDOQL.

With JDOQL you can specify the ordering using the normal JDOQL syntax for a parameter, and then add ascending or descending (UPPER or lower case are both valid) are to give the direction. In addition the abbreviated forms of asc and desc (again, UPPER and lower case forms are accepted) to save typing. For example, you may set the ordering as follows

query.setOrdering("productId DESC");


Set the grouping expressions, optionally including a "having" clause. When grouping is specified, each result expression must either be an expression contained in the grouping, or an aggregate evaluated once per group.

This is applicable to JDOQL.