JPOX
JPOX
 Project  |  Ver 1.1  |  Ver 1.2  |  JDO  |  JPA  |  Guides  |  Tools
1.1 | Preparation | O/R Mapping | Runtime | Extensions | Developer
JPOX 1.1 Runtime
Runtime Tools
Queries
RDBMS Datastores
JPOX Best Practices

Clearly JDO is complex and there are many ways of utilising it in your application. This section attempts to give a few pointers that you may find useful in avoiding issues. This guide should be read in conjunction with the Performance Tuning Guide.

Implementation Process

There should be 3 steps in your use of JDO.

  1. Deciding which classes to persist and how to persist them to the datastore
  2. Creating the schema or validating that it matches the persistence decisions taken in step 1
  3. Running your application

Many people like to perform steps 2 and 3 together because JPOX will support the creation of schemas dynamically. This can, however, confuse issues where the MetaData is incompatible with the existing schema for example, or where the MetaData definition is incorrectly specified. It is always best to use JPOX SchemaTool to either create the schema (where you are creating a new schema) or to validate it (where you are using an existing schema). This means that you isolate issues about the schema and MetaData before running your application.

Once you have isolated all issues around the schema and the MetaData you can then run your application. Since you know that the schema exists and is valid for your MetaData you can safely run with the properties org.jpox.autoCreateSchema, org.jpox.autoCreateTables, org.jpox.autoCreateColumns, org.jpox.autoCreateConstraints, org.jpox.validateTables, and org.jpox.validateConstraints all set to false. This will lead to much better performance for your application since fewer checks will be made at runtime of the schema structure.



Use of PersistenceManagerFactory's

Creation of PersistenceManagerFactory objects can be expensive and so is to be kept to a minimum. Depending on the structure of your application, use a single PersistenceManagerFactory per datastore wherever possible. Clearly if your application spans multiple servers then this may be impractical, but should be borne in mind.



Use of PersistenceManagers

Clearly the structure of your application will have a major influence on how you utilise a PersistenceManager. A pattern that gives a clean definition of process is to use a different PersistenceManager for each request to the data access layer. This reduces the risk of conflicts where one thread performs an operation and this impacts on the successful completion of an operation being performed by another thread. Creation of PersistenceManager's is not an expensive process.



Using objects outside of the datastore tier - detach/attach

When you need to use objects in a different layer of your application (outside of the datastore layer) you need a mechanism for taking the objects in a form where they can be used. JDO2 provides detach/attach functionality for this purpose. There are two ways of detaching objects. The first is to use PersistenceManager.detachCopy() however this can be computationally expensive since it has to create copies of the objects (and also down an object graph too if required). The second way is to use the PMF property javax.jdo.option.DetachAllOnCommit which means that the existing objects that have been enlisted in the current transaction are automatically migrated into detached state. This is not computationally expensive and means that you can now use your objects and update them directly before sending them back to the datastore layer for persisting.

... (create PMF with javax.jdo.option.DetachAllOnCommit set to true)

// Datastore Tier - persist any new objects
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try
{
    tx.begin();

    pm.makePersistent(myObj);

    tx.commit();
    // myObj is now detached
}
finally
{
    if (tx.isActive())
    {
        tx.rollback();
    }
}

// Business Tier - update your objects
... update "myObj" in your business layer

// Datastore Tier - persist any changes to your objects
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try
{
    tx.begin();

    // Attach the updated (detached) myObj
    pm.makePersistent(myObj);

    tx.commit();
    // myObj is now detached again for any further updates
}
finally
{
    if (tx.isActive())
    {
        tx.rollback();
    }
}

So the move to "detached" state is transparent and you can use your objects directly when they leave the datastore tier.