Multiple PersistenceManagers Accessing the Same Datastore
You can instantiate multiple
PersistenceManagers in your application from the same or
PersistenceManagerFactorys. Figure 3-3 illustrates an application with two
PersistenceManagers from the same
Figure 3-3. Application with multiple PersistenceManagers
PersistenceManager manages its
own transaction context and application cache. In this particular example,
PersistenceManagers access the same datastore
and are from the same JDO implementation. This is the typical architecture for
managed environments where different instances of the same component access
the same datastore via different
PersistenceManagers may have the
same datastore instance in their caches, represented by different persistent
instances. This architecture provides for transactional isolation of changes
made to the same datastore instance by different transactions.
Multiple PersistenceManagers Accessing Different Datastores
Figure 3-4 illustrates
different datastores. These
could be from the same or different implementations. For example, one
datastore may be a relational database and the other an object database. Due
to JDO's binary-compatibility contract (covered in Chapter 6),
PersistenceManagers from different implementations can
manage different instances of the same persistent classes. JDO is the first
database-interface technology to offer this high level of portability across
Figure 3-4. Application with multiple JDO implementations
Shared Implementation Cache
In addition to the application cache, some JDO implementations also maintain their own persistent instance cache that sits between the application cache and the datastore. Your application does not have access to this implementation cache. Its role is to cache the state of objects from the datastore in memory, so they can be provided to the application without requiring access to the datastore. Use of caches can result in significant performance improvements. A shared implementation cache is most useful when you use nontransactional access, covered in Chapter 14, or optimistic transactions, covered in Chapter 15. When you use datastore transactions, the shared cache is usually bypassed.
Shared implementation cache within a single JVM
Figure 3-5 illustrates a shared implementation cache that is managed within a
single JVM. It allows each of the
PersistenceManagers to quickly access the state of
objects that have been accessed from the same datastore.
Figure 3-5. Implementation of a shared cache for transactions accessing the same datastore
For example, if one
PersistenceManager accesses a particular instance, the
implementation needs to read the instance from the datastore. But if the other
PersistenceManager then accesses the same instance,
the implementation can use the data in the shared implementation cache and
avoid having to access the datastore.
Shared implementation cache distributed among JVMs
Several JDO implementations provide a distributed cache architecture, which allows them to migrate the state of objects between JVMs. Figure 3-6 illustrates this architecture.
Figure 3-6. Implementation use of distributed, synchronized caches
Again, the goal with these implementations is to avoid a datastore access whenever possible. For some systems where multiple applications may access the same objects, these implementations demonstrate substantial performance improvements.