11.5. Limits and Ordering
Prev | Chapter 11. Query | Next

## 11.5. Limits and Ordering

We have seen how you tell the query which objects you want. This section shows you how to also tell it how many objects you want, and what order you want them in.

    public void setUnique (boolean unique);
    public void setRange (long start, long end);

Use the `setUnique` method when you know your query matches at most a single object. A unique query always returns either the one candidate instance that matched the filter, or null; it never returns a `Collection`. In fact, unique queries enforce the one-result rule by throwing a `JDOUserException` if more than one candidate survives the filtering process.

While `setUnique` is designed for queries with only one result, `setRange` is designed for those with many. Most applications that deal with large amounts of data only process or display a fixed number of records at a time. For example, a web app might show the user 20 results per page, though many thousands of records exist in the database. Using `setRange`, you can retrieve the exact range of objects you're interested in. The method behaves much like `List.subList` or `String.subString`: it uses 0-based indexes, and the `end` index is exclusive. Unlike these methods, however, `setRange` won't throw an exception when your range extends beyond the available elements. If 50 records exist and you ask for the range `40, 60`, you'll receive a collection containing the 41st (remember indexes are 0-based) through 50th result objects. If you ask for the range `60, 80`, you'll get an empty collection.

Whenever you don't specify a range on a query, it defaults to a start index of `0` and an end index of `Long.MAX_VALUE`, which represents no limit.

    public void setOrdering (String ordering);

Ranges are meaningless if the result order isn't constant between query executions, and many datastores don't guarantee consistent natural ordering. `setOrdering` gives you control over the order of results, so you don't have to rely on the vagaries of the datastore. The method's argument is a comma-separated list of field names or expressions, each followed by the keyword `ascending` or `descending`. Those keywords can be abbreviated as `asc` and `desc` respectively. Results are ordered primarily by the first (left-most) expression. Wherever two results compare equal with that expression, the next ordering expression is used to order them, and so on.

Example 11.11. Unique

Find the magazine "Spaces" published by Manning. We know that this query can only match 0 or 1 magazines, so we set the `unique` flag to avoid having to extract the result object from a `Collection`.

    PersistenceManager pm = ...;
    Query query = pm.newQuery (Magazine.class,
        "publisher.name == 'Manning' && title == 'Spaces'");
    query.setUnique (true);
    processMagazine ((Magazine) query.execute ());

Example 11.12. Result Range and Ordering

Order all magazines by price and return the 21st through 40th results.

    PersistenceManager pm = ...;
    Query query = pm.newQuery (Magazine.class);
    query.setOrdering ("price ascending");
    query.setRange (20, 40);
    Collection mags = (Collection) query.execute ();
    for (Iterator itr = mags.iterator (); itr.hasNext ();)
        processMagazine ((Magazine) itr.next ());
    query.close (mags);

Prev | Up | Next
11.4. Compiling and Executing Queries | Home | 11.6. Projections