Persistence-aware applications are applications
that make use of persistence-capable objects. In theory, programmers responsible
for developing persistence-aware applications can be different from programmers
responsible for constructing the persistence-capable classes. The former deal
with business logic while the latter deal with data modeling. In practice,
depending on the situation, these two groups of programmers could be one and the
same.

The PE:J JDO runtime allows application programmers to manipulate
persistence-capable objects the same way they manipulate common Java objects. In
addition, functions are provided to enable transactional persistence (storage of
objects in a data-store). Application programmers can have a consistent
Java-centric view of persistent data without the need to learn a detailed
data-store-specific query language (SQL, etc.) or many dialect variations of
the query language of different database vendors. As far as the application
programmers are concerned, the actual interactions between the data-store and the
data are transparent. They do not need to know how the actual interactions are
performed behind the scenes, or even what database system is being used.

The java interfaces of JDO are defined in the package javax.jdo.
Persistence-aware applications make use of these interface to access
persistence-capable objects. Furthermore, the PE:J JDO Runtime also provides
convenience classes like the JDOAdapter to pool Persistence Manager
Factory instances, and Oid to generate unique UUIDs. These are found in
the com.hywy.pej.adapter.JDOAdapter
class
and the com.hywy.pej.persistence.oidserver.Oid
class
respectively.

Note:
This article assumes that the reader has already created the
simple bank project using PE:J and JDO.

The following demonstrates how to
develop a Persistence-Aware Application that makes use of the JDO Enhanced
Persistence-Capable classes and the JDO API.

All persistence-aware applications
will need to perform certain common steps. They are:

Obtain a Configured Persistence Manager Factory (PMF) from the JDOAdapter

1. Obtain a Configured PersistenceManagerFactory
(PMF) from the JDOAdapter

The Persistence Manager Factory is
responsible for creating persistence managers according to pre-configured
options and closing them. All options of the PE:J JDO runtime are stored in the
Persistence Manager Factory. In addition, pooling of persistence managers is
also implemented in the PE:J JDO runtime.

Lines 83 to 93 in the code listing
of the Teller class below, provide an example
of how to obtain a pre-configured PMF. (It has been reproduced here for your
convenience)

A persistence-aware application
must create a persistence manager. The Persistence Manager is a high-level
programming interface for managing the states of persistence objects,
transactions and queries. An instance of the persistence manager can be obtained
from the persistence manager factory. The persistence manager obtained will use
the options and connections defined by the persistence manager factory.

Line 125 in the code listing of the
Teller class below, provides an example of how
to obtain a persistence manager from the PMF. (It has been reproduced here for
your convenience)

// Obtain a Persistence Manager from the Factory ObjectPersistenceManager pManager=pmFactory_.getPersistenceManager();

3. Use the Persistence Manager (PM)
to obtain a Transaction object

Usually several operations on
persistence-capable objects are grouped as a transaction. A transaction object
can be accessed by the method currentTransaction(). A transaction will be
started by calling the begin() method.

Line 128 in the code listing of the
Teller class below, provides an example of how to obtain a transaction object
from the PM, and Line 131 provides an example of how to begin a transaction. (It
has been reproduced here for your convenience)

// Retrieve a Transaction object from the Persistence ManagerTransaction transaction=pManager.currentTransaction();

// Begin a Transactiontransaction.begin();

4. Inserting, selecting, updating or
deleting a persistence-capable object
Persistence-capable objects are obtained from the persistence manager. The
values of their fields can be modified thereafter. Once the objects are loaded,
they are saved inside the object cache of the persistence manager. Objects are loaded
on demand. Application programmers do not usually need to manage the object cache
explicitly. Any unused/unreferenced objects are automatically garbage-collected by
the Java runtime.

Line 134 in the code listing of the
Teller class below, provides an example of how to insert a new object. (It has
been reproduced here for your convenience)

// Invoke Make Persistent on the objectpManager.makePersistent(account);

Line 196 in the code listing of the
Teller class below, provides an example of how to delete a persistence-capable
object. (It has been reproduced here for your convenience)

When a transaction commits, all the operations on
the persistence objects will be flushed to the data-store. Updates, insertions and
deletions of data in the data-store will be performed if necessary. The
data-store
operations can also be aborted by rolling back a transaction. After committing
the transaction, the persistence manager can be re-used and another new
transaction can be started. At any one time, a persistence manager can deal with
only one transaction.

Lines 136 to 148 in the code
listing of the Teller class below, provide an example of how to commit or
rollback a transaction. (It has been reproduced here for your convenience)

6. Closing the Persistence Manager
Close the persistence manager by calling the close() method. The closed
persistence manager is collected by the factory into its pool of available
persistence managers for future use.

Line 153 in the code listing of the Teller class below, provides an example of
how to close a persistence manager. (It has been reproduced here for your
convenience)

// Close the Persistence Managerif(pManager!=null) {pManager.close();}

7. Release the Persistence Manager
Factory

Release the persistence manager
factory by calling the close() method on the JDOAdapter instance. The released
persistence manager factory is collected by the JDOAdapter into its pool of
available persistence manager factories for future use.

Line 75 in the code listing of the
Teller class below, provides an example of how to close a persistence manager.
(It has been reproduced here for your convenience)

this.adapter_.close(datastoreName,pmFactory);

The class diagram of the Teller
class below, lists the attributes, and public methods of the Teller Application.

The code listing of the Teller
class below, demonstrates how to develop a Persistence-Aware Application
that makes use of the JDO Enhanced Persistence-Capable classes.

Place the following file in the Enhanced Folder that you identified in PE:J

/** * Releases the configured PMF and returns it back to the Object Pool, * so that it can be reused by some other process * * @param
datastoreName - string denoting the name of the pre-configured datastore * @param pmFactory - PersistenceManagerFactory object that can be released back to the pool */public voidreleasePMF(String
datastoreName,PersistenceManagerFactory pmFactory) {this.adapter_.close(datastoreName,pmFactory);}

An extent is a JDO construct that is leveraged
both for performance and as a basis for JDO object queries. An extent represents
all of the instances of a class or a class and its subclasses. Extents could be
thought of as collections, but with some room for optimization. A JDO
implementation can implement an extent such that only batches of returned
objects are actually immediately available in memory. In this case, the
remaining objects become populated by the JDO implementation one by one, or in
groups, as the iterator encounters objects that are not available in memory. The
ability to lazily load objects is an improvement over collections, which can
require the JDO provider to load thousands of objects to represent a table.

Lines 403 to 427 in the code listing of the
Teller class above, provide an example of how to use a JDO Extent.
(It has been reproduced here for your convenience)

// Obtain a Persistence Manager from the Factory ObjectpManager=pmFactory_.getPersistenceManager();

Note that a JDO extent is retrieved through the
persistence manager. The parameters are as follows:

The class of instances that the extent is
based on

Whether subclasses should be included

Finally, the extent should be closed. This
closes all iterators over an extent. After this point, all iterators will
return false from their hasNext method.

Upon retrieval of the extent, we get an iterator (just like a collection)
and iterate through the contents. The contents of the collection that are
printed are all of the Savings Accounts that were created.

The Transfer Money Operation

The Transfer Money Object
Interaction Diagram is as shown below:

The Transfer Money logic is as
follows:

The JDO Client (Teller.java)
obtains a configured PersistenceManagerFactory (PMF) from the JDOAdapter.

The JDO Client (Teller.java)
uses the configured PMF to get a PersistenceManager.

The JDO Client (Teller.java)
uses the Persistence Manager to obtain a Transaction object.

The JDO Client (Teller.java) begins
a new Transaction using the Transaction object.

The JDO Client (Teller.java)
invokes the credit method on the Checking object.

The JDO Client (Teller.java) then
invokes the debit method on the Savings object.

The JDO Client (Teller.java) then
commits the transaction by invoking the method in the Transaction object.

The JDO Client (Teller.java) then
closes the Persistence Manager.

The JDO Client (Teller.java) then
closes the JDOAdapter.

Create a file called Teller.java
and place it in the %PEJ_HOME%\projects\bank\enhanced
folder. Compile it once again from the PE:J Console. If in doubt, please
refer to the
Quick
Start Guide to see how to do this.