11.10. Named Queries
Prev | Chapter 11. Query | Next

## 11.10. Named Queries

Named queries provide a means to define complex or commonly used queries in metadata files. These queries have all the capabilities of queries created in code, including support for parameters, aggregates and projections.

You declare named queries in `.jdoquery` files. The query file format is quite similar to that of JDO metadata. In addition, query metadata files are stored in the same locations as JDO metadata. The `.jdoquery` XML structure includes attributes and elements which correspond to methods in the `javax.jdo.Query` interface.

    public Query newNamedQuery (Class cls, String name);

At runtime, you obtain named queries with the `PersistenceManager.newNamedQuery` method. The `Class` argument names the query's candidate class. This argument may be null if the query does not have a candidate class, as we'll see below. The `String` argument is the name of the query.

| Note
Until official JDO 2 jars are released, you will have to cast your persistence managers to the `kodo.runtime.KodoPersistenceManager` interface to access the `newNamedQuery` method.

Before returning a named query, the system populates it with the information provided in the `.jdoquery` metadata, then compiles it to make sure it is valid. You can still change the query before executing it, using the methods of the `Query` interface. These changes won't affect other query instances returned from subsequent calls to `newNamedQuery`.

### 11.10.1. Named Query DTD

The Document Type Definition (DTD) for named query metadata is very similar to JDO metadata. We discuss the various elements of the DTD below.

    <!ELEMENT jdoquery ((query)*, (package)*, (extension)*)>

    <!ELEMENT package ((class)+)>
    <!ATTLIST package name CDATA #REQUIRED>

    <!ELEMENT query ((declare)?, (filter|sql|jdoql)?, (result)?, (extension)*)>
    <!ATTLIST query name CDATA #REQUIRED>
    <!ATTLIST query language CDATA #IMPLIED>
    <!ATTLIST query ignore-cache (true|false) #IMPLIED>
    <!ATTLIST query include-subclasses (true|false) #IMPLIED>
    <!ATTLIST query filter CDATA #IMPLIED>
    <!ATTLIST query sql CDATA #IMPLIED>
    <!ATTLIST query jdoql CDATA #IMPLIED>
    <!ATTLIST query ordering CDATA #IMPLIED>
    <!ATTLIST query range CDATA #IMPLIED>

    <!ELEMENT filter (#PCDATA)>
    <!ELEMENT sql (#PCDATA)>
    <!ELEMENT jdoql (#PCDATA)>

    <!ELEMENT declare (extension)*>
    <!ATTLIST declare imports CDATA #IMPLIED>
    <!ATTLIST declare parameters CDATA #IMPLIED>
    <!ATTLIST declare variables CDATA #IMPLIED>

    <!ELEMENT result (#PCDATA)>
    <!ATTLIST result unique (true|false) #IMPLIED>
    <!ATTLIST result class CDATA #IMPLIED>
    <!ATTLIST result grouping CDATA #IMPLIED>

    <!ELEMENT extension (extension)*>
    <!ATTLIST extension vendor-name CDATA #REQUIRED>
    <!ATTLIST extension key CDATA #IMPLIED>
    <!ATTLIST extension value CDATA #IMPLIED>

You can define queries just below the root `jdoquery` element or at the `class` level. Queries within the `jdoquery` root do not have an automatic candidate class. These are usually single-string JDOQL queries with an inline candidate class declaration, or SQL projections, which we cover in the next chapter. Queries denoted in a `class` element are given that candidate class.

The `query` element details options like the query name, ordering, range, and whether to include subclasses in the results. You can include the filter string as an attribute at this level or as the text of a nested `filter` element.

Use the `declare` element to control variable, parameter, and import declarations.

The `result` element allows you to use aggregates, projections, custom result classes, unique results, and grouping.

Finally, you can forgo most of the elements and attributes above and express the query in single-string form. Use the `jdoql` attribute on the `query` element, or the nested `jdoql` element.

### 11.10.2. Named Query Examples

We will now examine some named query examples. We begin by looking at the metadata for a very simple query.

Example 11.24. Defining a Named Query

The XML below defines a query named `sports` for the `org.mag.Magazine` class. You might place this XML in the `org/mag/package.jdoquery` or `org/mag/Magazine.jdoquery` files.

    <?xml version="1.0"?>
    <jdoquery>
        <package name="org.mag">
            <class name="Magazine">
                <query name="sports" filter="title.startsWith ('Sports')"/>
            </class>
        </package>
    </jdoquery>

Declaring the named query above is equivalent to the following Java code:

    PersistenceManager pm = ...;
    Query query = pm.newQuery (Magazine.class);
    query.setFilter ("title.startsWith ('Sports')");
    query.compile ();

Here is a more complex case:

Example 11.25. Ordering, Range, Variables, and Parameters

    <xml version="1.0"?>
    <jdoquery>
        <package name="org.mag">
            <class name="Magazine">
                <query name="findBySub" ordering="title ascending" range="0,10">
                    <declare parameters="String sub" variables="Article art"/>
                    <filter>
                        articles.contains (art) &amp;&amp; art.subtitles.contains (sub)
                    </filter>
                </query>
            </class>
        </package>
    </jdoquery>

This query finds the first 10 magazines that have an article with a subtitle equal to `sub`, where `sub` is a string whose value you supply on execution. The results are ordered alphabetically on the magazine title. Note that we declare parameters and variables as attributes of the `declare` element. In addition, we define behavior such as ordering and result range as attributes of the `query` element.

Example 11.26. Single-String Named Query

Here is the same query as the previous example, using single-string form and implicit parameters and variables. Because the single-string form includes the candidate class, you can use it outside of a `class` element.

    <?xml version="1.0"?>
    <jdoquery>
        <query name="findBySub">
            <jdoql>
                select from org.mag.Magazine where articles.contains (art)
                    &amp;&amp; art.subtitles.contains (:sub)
                order by title ascending range 0, 10
            </jdoql>
        </query>
    </jdoquery>

Example 11.27. Aggregates and Projections

This example uses the `result` element to create an aggregate result. The query below returns each publisher and the average price of its magazines, for all publishers that publish less than 10 magazines. The results are packed into instances of the `PubPrice` class.

    <?xml version="1.0"?>
    <jdoquery>
        <package name="org.mag">
            <class name="Magazine">
                <query name="publishPrice">
                    <result grouping="publisher having count (this) < 10" class="PubPrice">
                        publisher, avg(price) as avgPrice
                    </result>
                </query>
            </class>
        </package>
    </jdoquery>

To obtain a named query you pass the query's candidate class (or null for queries outside of a `class` element) and name to the `PersistenceManager`. Once you have the `Query`, you can immediately execute it, optionally passing in values for any parameters the query declares.

Example 11.28. Executing Named Queries

    PersistenceManager pm = ...;
    Query query = pm.newNamedQuery (Magazine.class, "findBySub");
    Collection mags = (Collection) query.execute ("JDO");
    for (Iterator itr = mags.iterator (); itr.hasNext ();)
        processMagazine ((Magazine) itr.next ());
    query.close (mags);

Prev | Up | Next
11.9. Single-String JDOQL | Home | 11.11. Conclusion