In Chapter 8 we learned how to access all the instances of a class by using an Extent. Once we have accessed some instances from the datastore, we can navigate to other related instances in Java by traversing references and iterating through collections. This allows us to access an application-specific closure of related instances to perform the functionality provided by the application.
But when you iterate an Extent, you potentially access all the instances of a class. We may only care about one or a small number of instances of the class that meet certain criteria. Once these initial instances have been accessed, we typically then navigate to instances related to those initial instances. However, getting to the first few persistent instances is a bootstrap issue. JDO provides a query language, called JDO Query Language (JDOQL), that is used to access persistent instances based on specified search criteria.
You perform queries in JDO by using the Query interface. The PersistenceManager interface is a factory for creating Query instances, and queries are executed in the context of the PersistenceManager instance used to create the Query instance. JDO queries allow you to filter out instances from a set of candidate instances specified by either an Extent or a Collection. A filter consisting of a Boolean expression is applied to the candidate instances. The query result includes all of the instances for which the Boolean expression is true.
The JDO query facility was designed with the following goals:
Query language neutrality. The underlying query language might be a relational query language such as SQL, an object database query language such as the Object Data Management Group's (ODMG) Object Query Language (OQL), or a specialized API to a hierarchical database or mainframe EIS system.
Optimization to a specific query language. The query interface must be capable of optimizations; therefore, enough information should be specified so that the implementation can exploit datastore-specific query features. In particular, JDO specifies JDOQL so that all queries can be executed by a standard SQL-92 back-end datastore.
Accommodation of multitier architectures. A query may be executed entirely in application memory, delegated to a query engine running in a back-end datastore server, or executed using a combination of processing in the application and datastore server processes.
Large result set support. A query might return a massive number of instances. The query architecture must be able to process the results within the resource constraints of the execution environment.
Compiled query support. Parsing a query may be resource intensive. In many applications, the parsing can be done during application development or deployment prior to execution. The query interface must allow you to compile queries and bind values to parameters at runtime for optimal query execution.
The execution of a query might be performed by the PersistenceManager or it might be delegated to the underlying datastore. Thus, the actual underlying datastore query executed might be implemented in a language very different from Java, and it might be optimized to take advantage of a particular query-language implementation.