Cover | Table of Contents | Colophon
Movie instance represents a
particular movie. Each actor who has played a role in at least one
movie is represented by an instance of Actor. The
Role class represents the specific roles an actor
has played in a movie and thus represents a relationship between
Movie and Actor that includes
an attribute (the name of the role). Each movie has one or more
roles. An actor may have played a role in more than one movie or may
have played multiple roles in a single movie.com.mediamania.prototype package.Movie, Actor,
and Role classes persistent, so their instances
can be stored in a datastore. First we will examine the complete
source code for each of these classes. An import statement is
included for each class, so it is clear which package contains each
class used in the example.Movie class. JDO is defined in the
javax.jdo package. Notice that the class does not
require you to import any JDO-specific classes. Java references and
collections defined in the java.util package are
used to represent the relationships between our classes, which is the
standard practice used by most Java applications.Movie class use standard Java
types such as String, Date, and
int. You can declare fields to be private; it is
not necessary to define a public get and set method for each field.
The Movie class includes some methods to get and
set the private fields in the class, though those methods are used by
other parts of the application and are not required by JDO. You can
use encapsulation, providing only the methods that support the
abstraction being modeled. The class also has static fields; these
are not stored in the datastore.http://www.jcp.org and selecting JSR-12. Once
you have installed a JDO implementation, you will need to establish a
project directory structure and define a classpath that includes all
the directories and jar files necessary to build and run your
application.javax.jdo package.PersistenceManager
that has a connection with a datastore. A
PersistenceManager has an associated instance of
the JDO Transaction interface used to control the
start and completion of a transaction. The
Transaction instance is acquired by calling
currentTransaction(
) on the PersistenceManager instance.PersistenceManagerFactory is used to configure
and acquire a PersistenceManager. Methods in the
PersistenceManagerFactory are used to set
properties that control the behavior of the
PersistenceManager instances acquired from the
factory. Therefore, the first step performed by a JDO application is
the acquisition of a PersistenceManagerFactory
instance. To get this instance, call the following static method of
the JDOHelper class:static PersistenceManagerFactory getPersistenceManagerFactory(Properties props);
Properties instance can be populated
programmatically or by loading property values from a property file.
Example 1-6 lists the contents of the property file
we will use in our Media Mania application. The
PersistenceManagerFactoryClass
property on line [1] specifies which JDO
implementation we are using by providing the name of the
implementation's class that implements the
PersistenceManagerFactory interface. In this case,
we specify the class defined in Sun's JDO reference
implementation. Other properties listed in Example 1-6 include the connection URL used to connect to
a particular datastore and a username and password, which may be
necessary to establish a connection to the datastorePersistenceManager to access and update the
datastore. Example 1-8 provides the source for the
MediaManiaApp class, which serves as the base
class for each application in this book. Each application is a
concrete subclass of MediaManiaApp that implements
its application logic in the execute( ) method.MediaManiaApp has a constructor that loads the
properties from jdo.properties (line [1]). After loading properties from the file, it
calls getPropertyOverrides( ) and merges the
returned properties into jdoproperties. An
application subclass can redefine getPropertyOverrides(
) to provide any additional properties or change properties
that are set in the jdo.properties file. The
constructor gets a PersistenceManagerFactory (line
[2]) and then acquires a
PersistenceManager (line [3]). We also provide the
getPersistenceManager( ) method to access the
PersistenceManager from outside the
MediaManiaApp class. The
Transaction associated with the
PersistenceManager is acquired on line [4].executeTransaction( ), defined in the
MediaManiaApp class. This method begins a
transaction on line [5]. It then calls
execute( ) on line [6],
which will execute the subclass-specific functionality.execute( ) method
(implemented by a subclass), an attempt is made to commit the
transaction (line [7]). If any exceptions
are thrown, the transaction is rolled back and the exception is
printed to the error stream.package com.mediamania;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
import java.util.Map;
import java.util.HashMap;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
public abstract class MediaManiaApp {
protected PersistenceManagerFactory pmf;
protected PersistenceManager pm;
protected Transaction tx;
public abstract void execute( ); // defined in concrete application subclasses
protected static Map getPropertyOverrides( ) {
return new HashMap( );
}
public MediaManiaApp( ) {
try {
InputStream propertyStream = new FileInputStream("jdo.properties");
Properties jdoproperties = new Properties( );
jdoproperties.load(propertyStream); javax.jdo
and
javax.jdo.spi
. You use the
interfaces defined in the javax.jdo package to
write your applications. This chapter introduces and describes each
of these interfaces at a high level. Each method defined in these
interfaces is covered thoroughly in this book. You can use the index
to find information on a particular method.javax.jdo.spi package contains interfaces that
JDO implementations use (spi stands for
service provider interface). It is a common
practice to have such a package that defines interfaces for use by
the implementation of a Java API, distinct from the package that
contains the interfaces for use of the API. You should not directly
use any of the interfaces defined in
javax.jdo.spi. We provide brief coverage of a few
of the javax.jdo.spi interfaces that are directly
involved in the management of persistent class instances. If you are
interested in a thorough understanding of the interfaces in
javax.jdo.spi, we encourage you to read the JDO
specification.javax.jdo package contains all the interfaces
you should use:PersistenceManager
PersistenceManagerFactory
Transaction
Extent
Query
InstanceCallbacks
JDOHelper class and a set of
exception classes.javax.jdo package contains all the interfaces
you should use:PersistenceManager
PersistenceManagerFactory
Transaction
Extent
Query
InstanceCallbacks
JDOHelper class and a set of
exception classes.PersistenceManager
PersistenceManager is your primary interface when
using JDO. It provides methods to create query and transaction
objects, and it manages the lifecycle of persistent instances. Each
chapter introduces a few PersistenceManager
methods. The interface is used for the basic and advanced features in
JDO.javax.jdo.spi
package defines interfaces
used by JDO implementations. Your application should not use the
interfaces in this package. However, a few interfaces in this package
are useful for you to be aware of, as they are directly responsible
for managing the state of persistent instances.PersistenceCapable
PersistenceCapable interface allows an
implementation to manage the values of fields and the lifecycle state
of persistent instances. Every instance managed by a
PersistenceManager needs to be of a class that
implements PersistenceCapable. When you enhance a
persistent class, code is added to the class to implement the
PersistenceCapable interface.PersistenceCapable
methods added by the enhancer. Some of its methods provide
information useful to your application; these methods are made
accessible to you through the JDOHelper and
PersistenceManager interfaces.StateManager
StateManager instance. (Chapter 13 covers transactional instances.) A
StateManager interfaces with the
PersistenceManager and is responsible for managing
the values of fields and state transitions of an instance. (Chapter 11 covers state transitions.)JDOPermission
JDOPermission
class is used to grant the JDO implementation permission to perform
privileged operations if you have a Java security manager in your Java
runtime environment. JDOPermission extends
java.security.BasicPermission. The following
permissions are defined:javax.jdo.option
prefix. You can call the supportedOptions( )
method, defined in PersistenceManagerFactory, to
determine which options an implementation supports; it returns a
Collection of Strings that
contain an option string. Chapter 7 presents an
example using this method. Here we enumerate all the optional
features and their names.javax.jdo.option.ApplicationIdentity
javax.jdo.option.DatastoreIdentity
javax.jdo.option.NonDurableIdentity
javax.jdo.option.ChangeApplicationIdentity
PersistenceManagers accessing the
same or different datastores concurrently. Each
PersistenceManager has its own persistent instance
cache
and its own associated Transaction instance, which
manages a distinct transactional context. A JDO implementation may
also maintain a shared cache of instances (not visible to
applications) to optimize the application's access
of data in the datastore.PersistenceManager, as illustrated in Figure 3-1. A PersistenceManager is
the primary interface used by the application to access persistent
services. It is an interface that is implemented by an instance of
the JDO implementation. The persistent instances are managed in a
cache, where they are used directly by the
application. The JDO implementation manages the persistent instances
both by using application control (e.g., using
PersistenceManager and Query
methods), and transparently (when the application accesses a field
that is not loaded). The cache contains other
artifacts, used to track the identity and state
of the instances, but these artifacts are not visible to the
application. Whenever we mention the cache, we
are referring to the cache of persistent instances.
jdoStateManager
,
added by the enhancer to reference a
StateManager
.
The StateManager manages the field values and
lifecycle state of the instance, and has a reference to its
associated PersistenceManager. A
PersistenceManager may use one or more
StateManagerConnectionURL property of the
Properties instance used to construct the
PersistenceManagerFactory refers to a local or
remote datastore.
doGet(
)
or doPost(
)
request and uses JDO to implement the request. Your application may
use the
Struts
framework to implement the servlets and JSP pages in this
architecture. We will discuss the web-server access patterns in
detail in Chapter 16.Movie, Actor, and
Role that we introduced in Chapter 1 are JDO-transparent, because they never made
an explicit call to the JDO API. On the other hand, the
private
,
public
,
protected
,
static
,
transient
,
abstract
,
final
,
synchronized
,
and
volatile
.
In some cases, as we will explore later in this chapter, some of
these modifiers cannot be used with persistent fields.java.net.SocketImpl or uses
Java Native Interface (JNI)), you cannot
make the class persistent. You also cannot have a persistent
nonstatic inner class, because the state
of the inner class instance depends on the state of its enclosing
instance.java.lang, java.io,
java.net, etc.) cannot be persistent. They are
also not allowed to be the type of a persistent field. This includes
classes such as
System
,
Thread
,
Socket
,
and
File
.
We list the system classes that are supported in Table 4-2 later in this chapter. You may be using an
implementation that supports additional system-defined classes,
especially those for modeling state information. Relying on support
for these additional types will make your software dependent on that
implementation.private
,
public
,
protected
,
static
,
transient
,
final
, and
volatile
.
But static and final fields
cannot be persistent, as we will discuss later in this chapter.field
metadata element. Its required
name
attribute should have the name of the field in the Java class
declaration. It has attributes to control the
field's persistence and the type of its elements if
it is a collection. We cover these attributes later in this chapter.
If the class uses application identity, one or more fields need to
indicate they are a primary-key field; Chapter 10
covers this in detail. Chapter 12 addresses
advanced field-management facilities enabled by the remaining
field element attributes.|
Java modeling construct
|
Relational modeling construct
|
|---|---|
|
Class
|
Table
|
|
Field
|
Column
|
|
Instance
|
Row
|
|
Identity
|
Primary key
|
|
Reference
|
Foreign key
|
|
Interface
|
No relational equivalent
|
|
Collection
|
No relational equivalent
|
|
Class inheritance
|
One or multiple tables
|
extension element nested within the
class
element. For example, the following example illustrates the metadata
necessary to map the MediaItem class
to a table called Items:<class name="MediaItem" >
<field name="rentalItems">
<collection
element-type="RentalItem"/>
</field>
<extension
vendor-name="vendorX" key="table" value="Items" />
<extension vendor-name="vendorY" key="sqlname" value="Items" />
</class>
vendor-name attribute. As we mentioned previously,
the datastore mappings in JDO 1.0.1 are implementation-specific. This
may be standardized in JDO 2.0. Each JDO vendor provides
documentation explaining which value to use for the
vendor-name attribute and which values are
supported for the key attribute.vendorX and
vendorY. An implementation will use only metadata
extensions that it recognizes. This allows you to place the metadata
for multiple vendors in the same JDO metadata file.
vendorX uses a value of "table"
for the key attribute to indicate which relational
table the MediaItem class should be mapped to, and
vendorY uses the value
"sqlname". You should check the
implementation's documentation to see which values
they require. We provide the name of the table
(Items) in the relational schema in the
value attribute. If you were to port your
application to another JDO implementation, you would need to add an
extension element that has values in the
vendor-name and key attributes
that are appropriate for that implementation. However, your Java
class would not have to change.