The Persistence Services of JDO


JDO provides the full range of persistence services. Persistence services are sometimes called CRUD for Create, Retrieve, Update, and Delete. In JDO, the Create, Retrieve, and Delete services are explicit; that is to say, JDO provides methods to add, find, or delete specific objects. On the other hand, the Update service is transparent; that is to say, JDO does not offer an update method that the application calls for those objects whose persistent state has been modified. Instead, the Update service occurs implicitly as a result of committing the transaction. In fact, whenever it is reasonable to do so, JDO creates and retrieves persistent objects transparently as well.

Transactions

Transactions are not on the list of CRUD services, but they are an integral part of JDO. JDO provides transactional semantics and the explicit methods to begin and complete transactions. Applications that use JDO can modify the persistent state in the datastore only within a transaction. The modifications, including additions and deletions, are committed to the datastore only when the JDO transaction commits.

When a service supports transactional behavior, the client that uses the service can group its interactions with the service into units of work called transactions. The transactional service guarantees that the client, when it is ready to end a transaction, has two options. The client can ask the service to commit the work, and if the service is able to do this, then the results of all of the interactions are accepted and stored. On the other hand, the client can ask the service to roll back the work, and in this case, the service discards any modifications made within the transaction. Either way, the client gets all or nothing. Either everything is committed or nothing is committed. The service may not be able to commit, in which case, the client has no choice but to roll back. The service can always roll back, and if it doesn't receive a request to commit or roll back from the client, it will eventually roll back the transaction on its own. The all-or-nothing behavior of transactions is called atomicity.

Atomicity is just one of the four required properties of a transactional service. The transactional service must also guarantee that the work of a transaction, once committed, cannot be lost. This property is called durability. Transactional services are responsible for preventing multiple clients from interacting with each other in unpredictable ways. This property is called isolation. Transactional services are responsible for ensuring that the state, when stored, satisfies the defined rules for consistency. For example, if one of the rules is that the date of birth cannot be null, then the transactional service is responsible for refusing to commit any state that violates the rule. Taken together, these four properties of a transactional service, atomicity, consistency, isolation, and durability, are called the ACID properties of transactions.

In JDO, transactions are an explicit service available through the Transaction interface. JDO's transactions support the ACID properties. One Transaction object is associated with each persistence manager, and therefore each persistence manager supports one active transaction at a time. The Transaction interface provides methods to begin, commit, and roll back transactions. The Transaction interface is covered in Chapter 4.

Creating Persistent Objects

The application creates new objects of the application data classes whenever it likes by invoking the Java new operator. These newly created objects do not correspond to any state in the datastore, and for that reason they are called JDO-transient objects. Because JDO is not aware of the existence of JDO-transient objects, they are also called unmanaged objects. The application can make unmanaged application data objects persistent by calling the persistence manager's makePersistent method. Thereafter, the application relies on JDO to insert the state of the newly made persistent object into the datastore when the transaction commits.

Objects can also be made persistent implicitly by assigning an unmanaged object to the persistent field of a persistent object. When the transaction commits, JDO follows the reference in the persistent field to the unmanaged object and makes it persistent as well. This action is a JDO feature called persistence by reachability, and it serves as an example of transparent persistence.

Retrieving Persistent Objects

JDO provides several ways to retrieve persistent objects:

  • The application can retrieve persistent objects individually by JDO identity.

  • It can iterate all the persistent objects of an application data class using an extent.

  • It can iterate a collection of objects that satisfy a query.

To retrieve persistent objects by any of these methods requires one or more explicit calls to JDO. Chapter 2 describes extents and queries.

In addition, JDO will retrieve objects transparently when the application's code uses the references to persistent objects that are contained within other persistent objects. Unlike serialization, which loads the entire graph of interconnected objects into memory at once, JDO loads the objects as the references to them are used. This feature of JDO is called transparent navigation.

As an example of transparent navigation, consider an application that has two application data classes, Person and Dog. As Listing 1-1 shows, the Person class has a member field that refers to a Dog object, and getter-setter methods to set and return the Dog reference.

Listing 1-1: A Person and His or Her Dog

start example
 public class Person    {    private Dog myDog;    // ... other member fields omitted for brevity    public Dog getDog()       {       return myDog;       }    public void setDog(Dog newDog)       {       myDog = newDog;       }    // ... other methods omitted for brevity    } 
end example

When the application needs the reference to the dog that the person owns, it executes the following code:

 // somehow we have a reference to a persistent person Dog dog = person.getDog(); // ... do something with the dog 

This example shows transparent persistence at work. Because the application data classes were enhanced, when the myDog reference is used as the return value in the getDog method shown in Listing 1-1, JDO either finds in memory or creates in memory the persistent Dog object that the person owns. The application programmer does not write code to make this happen. JDO provides this service transparently for persistent application data objects.

Updating Persistent Objects

The application does not explicitly request that JDO update information in the datastore. Instead, the application modifies the persistent object in memory either by setting a member field's value or by calling a setter method. When the persistent object's state changes, the code that the enhancer added to the application data class notifies JDO of the change. As a result, the object becomes transactional and JDO takes responsibility for ensuring that the change is flushed to the datastore when the transaction commits.

Using the example of the Person and Dog classes again, the code in Listing 1-2 starts a transaction, makes a change to a persistent Person object, and commits the transaction.

Listing 1-2: Storing Modifications Upon Transaction Commit

start example
 // somehow, we have a reference to the persistence manager pm.currentTransaction().begin(); // somehow we have a reference to a persistent person // and to a persistent, but unowned, dog person.setDog(poundDog); pm.currentTransaction().commit(); 
end example

The important code in Listing 1-1 and Listing 1-2 is the code that is not there. The setDog method, like the getDog method, is not special. It simply assigns the parameter to the myDog field. As a result of transparent persistence, JDO tracks the change and knows that the Person object and its myDog field have changed. If the object wasn't transactional before the change was applied, it becomes transactional. When the transaction commits, JDO writes the change to the datastore. From the point of view of the application, the code that modifies a Person object is not entangled with the code that controls the transaction's boundaries.

Deleting Persistent Objects

When the time comes to remove a persistent object's state from the datastore, the application calls the persistence manager's deletePersistent method. After deletePersistent is called, the state of the deleted object is removed from the datastore when the transaction commits.

JDO does not provide a general mechanism to implicitly delete objects. Using the example of persons and dogs once again, it is not the case that deleting the dog's owner will cause the dog to be deleted transparently. However, some JDO implementations may provide for cascading deletes in a manner that is implementation dependent. In addition, the application can implement cascading deletes by using the InstanceCallbacks interface, as described in Chapter 7.

Although JDO provides the API to insert, delete, and find objects with persistent state, much of the simplicity and power of JDO comes from the persistence services that are provided transparently to the application. Persistence by reachability, transparent navigation, and implicit updating of the datastore upon transaction commit are three important examples of transparent persistence. Transparent persistence arises because many interactions between persistent objects and JDO are hidden from the application. The code that supports the interaction is inserted into the application data classes in the enhancement step.




Using and Understanding Java Data Objects
Using and Understanding Java Data Objects
ISBN: 1590590430
EAN: 2147483647
Year: 2005
Pages: 156
Authors: David Ezzio

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net