Chapter 3. JDO Architecture
Prev | Part 3. Java Data Objects | Next

## Chapter 3. JDO Architecture

The diagram below illustrates the relationships between the primary components of the JDO architecture.

- `JDOHelper`: The `javax.jdo.JDOHelper` contains static helper methods to query the lifecycle state of persistent objects and to obtain `PersistenceManagerFactory` instances in a vendor-neutral fashion.

- `PersistenceManagerFactory` : The `javax.jdo.PersistenceManagerFactory` is a factory for `PersistenceManager`s.

- `PersistenceManager`: The `javax.jdo.PersistenceManager` is the primary JDO interface used by applications. Each `PersistenceManager` manages a set of persistent objects, and has APIs to insert new objects and delete existing ones. There is a one-to-one relationship between a `PersistenceManager` and a `Transaction`. `PersistenceManager`s also act as factories for `Extent` and `Query` instances.

- `PersistenceCapable`: JDO calls user-defined persistent classes persistence-capable classes. Most JDO vendors provide an enhancer to transparently add a special `PersistenceCapable` interface to each persistent class. You will never use this interface directly.

- `Transaction`: Each `PersistenceManager` has a one-to-one relation with a single `javax.jdo.Transaction`. `Transaction`s allow operations on persistent data to be grouped into units of work that either completely succeed or completely fail, leaving the datastore in its original state. These all-or-nothing operations are important for maintaining data integrity.

- `Extent`: A `javax.jdo.Extent` is a logical view of all the objects of a particular class that exist in the datastore. You can configure `Extent`s to also include subclasses. `Extent`s are obtained from a `PersistenceManager`.

- `Query`: The `javax.jdo.Query` interface is implemented by each JDO vendor to find persistent objects that meet certain criteria. JDO standardizes support for queries using the Java Data Objects Query Language (JDOQL), and for relational database queries using the Structured Query Language (SQL). You obtain `Query` instances from a `PersistenceManager`.

- `FetchPlan`: Each `PersistenceManager` and `Query` has a mutable reference to a `javax.jdo.FetchPlan`. The `FetchPlan` gives you control over eager fetching, result scrolling, and other data loading behavior.

- `Sequence`: The `javax.jdo.datastore.Sequence` interface represents an object capable of generating sequential values. Sequences are defined in mapping metadata (see Chapter 15, Mapping Metadata), cached at the `PersistenceManagerFactory` level, and obtained through the `PersistenceManager`.

- `DataStoreCache`: Many JDO implementations provide some form of datastore cache. The `javax.jdo.datastore.DataStoreCache` interface provides a standard way to interact with your vendor's cache.

The example below illustrates how the JDO interfaces interact to execute a JDOQL query and update persistent objects.

Example 3.1. Interaction of JDO Interfaces

    // get a PersistenceManagerFactory using the JDOHelper; typically
    // the factory is cached for easy repeated use
    PersistenceManagerFactory factory =
        JDOHelper.getPersistenceManagerFactory (System.getProperties ());

    // get a PersistenceManager from the factory
    PersistenceManager pm = factory.getPersistenceManager ();

    // updates take place within transactions
    Transaction tx = pm.currentTransaction ();
    tx.begin ();

    // query for all employees who work in our research division
    // and put in over 40 hours a week average
    Extent extent = pm.getExtent (Employee.class, false);
    Query query = pm.newQuery (extent);
    query.setFilter ("division.name == 'Research' && avgHours > 40");

    // we only need to populate the metadata-defined salary fetch group data;
    // there might be a lot of employees, so read from store in batches of 100
    query.getFetchPlan ().setGroup ("salary");
    query.getFetchPlan ().setFetchSize (100);
    List results = (List) query.execute ();

    // give all those hard-working employees a raise; keep track of hardest worker
    Employee emp;
    Employee mostHours = null;
    for (Iterator itr = results.iterator (); itr.hasNext ();)
    {
        emp = (Employee) itr.next ();
        emp.setSalary (emp.getSalary () * 1.1);
        if (mostHours == null || emp.avgHours () > mostHours.avgHours ())
            mostHours = emp;
    }

    // we know we're going to be fetching the hardest-working employee a
    // lot in our application, so pin its data to the cache
    factory.getDataStoreCache ().pin (JDOHelper.getObjectId (mostHours));

    // commit the updates and free persistence manager
    tx.commit ();
    pm.close ();

    // if we were ending our application, we'd free the factory too
    // factory.close ();

The remainder of this document explores the JDO interfaces in detail. We present them in roughly the order that you will use them as you develop your application.

## 3.1. JDO Exceptions

The diagram above depicts the JDO exception architecture. Runtime exceptions such as `NullPointerException`s and `IllegalArgumentException`s aside, JDO components only throw `JDOException`s.

The JDO exception hierarchy should be self-explanatory. The base `JDOException` class provides the following useful properties:

- `FailedObject`: The failed object is the persistent instance or identity object that caused the exception, if applicable. It is particularly useful for `JDOOptimisticVerificationException`s and `JDOObjectNotFoundException`s.

- `NestedExceptions`: An array of nested exceptions that caused the failure. Rather than stop immediately at the first error, many JDO methods collect all errors during execution and throw a single parent exception, nesting the collected exceptions within it. For example, a failed attempt to commit a transaction might result in a `JDOFatalDataStoreException` with a nested `JDOOptimisticVerificationException` for each persistent instance that failed the optimsitic concurrency check.

See the Javadoc for additional details on JDO exceptions.

Prev | Up | Next
Chapter 2. Why JDO? | Home | Chapter 4. PersistenceCapable