Managed and Unmanaged Objects


In order to provide persistent services for the application's data objects, JDO must manage the objects. Within a Java Virtual Machine (JVM), JDO manages some objects and does not manage other objects. If JDO manages an object, it manages its persistent state, or its transactional state, or both. JDO is able to manage the objects of certain classes, while it cannot manage the objects of other classes. Those classes whose objects JDO can manage are called the persistence-capable classes.

The persistence-capable classes include all the application data classes. These are the classes that the application defines for the primary purpose of holding persistent state. These classes are enhanced, usually during the build process.

In addition, JDO identifies system classes from the java.* packages that implementations must in some cases, or may in other cases, support as persistence-capable classes. Every JDO implementation must or may support the following system classes:

  • Arrays (optional)

  • ArrayList (optional)

  • BigDecimal

  • BigInteger

  • Boolean

  • Byte

  • Character

  • Date

  • Double

  • Float

  • HashMap (optional)

  • HashSet

  • Hashtable (optional)

  • Integer

  • LinkedList (optional)

  • Locale

  • Long

  • Short

  • String

  • TreeMap (optional)

  • TreeSet (optional)

  • Vector (optional)

These classes are called the supported system classes.

The member fields of an application data class are divided into three groups: persistent fields, transactional fields, and unmanaged fields. The persistent fields and the transactional fields, taken together, are called the managed fields. JDO can manage persistent fields both persistently and transactionally, while it can manage transactional fields only transactionally. JDO ignores the unmanaged fields. The application programmer can specify in the JDO metadata, which is an XML file, whether a member field is persistent, transactional, or unmanaged. If the JDO metadata does not specify how the field is to be managed, the enhancer tool applies defaults that determine the management for the field. Chapter 5 explains the structure and default values of the JDO metadata.

When JDO manages an object persistently, it manages the synchronization of the object's persistent fields with the state stored in the datastore. The properties of the Transaction interface define when the synchronization occurs. After synchronization, the values of the object's persistent fields match the values found in the datastore. At the same time, JDO inserts new information into the datastore and deletes old information from the datastore to match the persistent objects added and deleted within the transaction.

When JDO manages an object transactionally, it manages both the persistent and transactional fields at and within transactional boundaries. Upon successful commit, the current values of the transactional fields are retained in memory, and the current values of the persistent fields are synchronized with the datastore. As determined by the RetainValues property in the Transaction interface, JDO may retain in memory the current values of the persistent fields after commit, or it may clear them to their Java default values. Upon rollback, the persistent state in the datastore remains unaffected by the changes made in the transaction. As determined by the RestoreValues property in the Transaction interface, the values of persistent fields and transactional fields may be restored to the values that the object had prior to being modified within the transaction. Chapter 4 describes the Transaction interface and its properties.

JDO may not manage a data object, or it may manage it transactionally, persistently, or both. JDO's management of the object also varies depending on whether the data object is a first class object or an embedded object.

First Class Objects and Application Data Objects

A first class object (FCO) is the primary kind of persistent object, and by default, all application data objects are first class objects. First class objects have many distinguishing features. A first class object has its own JDO identity. JDO identities will be described in detail in the section "The Three Types of JDO Identity" later in this chapter, but for now, it is sufficient to know that a JDO identity refers to one and only one object's state in the datastore. The datastore saves the state of a first class object independently of any other object. JDO saves in the datastore the relationships in memory between FCOs, and it re-creates the same relationships in memory when the objects are retrieved.

FCOs can be retrieved by queries and by JDO identity. FCOs usually have extents. An extent is an iterable grouping of all the objects in the datastore that are assignment compatible with an application data class. Chapter 4 explores the Extent interface.

FCOs track their dirty fields, that is to say, the managed fields that have changed within the current transaction. As a result of tracking, JDO can limit the datastore synchronization to the objects and even the field values that have changed.

The persistent fields of FCOs can be navigated within queries. Using the JDO query language, the programmer structures the query filter as a Boolean expression that tests persistent fields for particular values.

Second Class Objects and Embedded Objects

Although the concept of a second class object (SCO) is an old concept in discussions of object-oriented persistence, many Java programmers may be unfamiliar with the term. A String object is a good example of a second class object.

In the following code that briefly defines the class Dog, the weight of the dog is represented by a member field of type float, and the name of the dog is represented by a member field of type String. The objects of the Dog class are first class objects and the objects of the String class are second class objects.

 public class Dog    {    private float weight;    private String name;    // ... constructors, getter-setter methods    // and business methods are omitted for brevity    } 

In memory, the name field refers to a String object that contains the dog's name. In memory, the String object's lifetime may be independent of the Dog object's lifetime. In addition, several dogs may share the same name by sharing the same String object.

The relationship between the dog and its name is quite different in the datastore. In most datastores, the dog's persistent state contains his weight in one field and his name in another. If the dog's state is removed from the datastore, his name and weight are removed with it. If information about three dogs named "Lilly" is stored in the datastore, then the name "Lilly" appears three times in the datastore as the value of the name field of three different dogs.

The architecture of the datastore determines what classes of objects are stored as second class objects. Most datastores store the objects of the supported system classes as second class objects.

Embedded objects are nearly the same thing as second class objects, except that you are looking at them from the JDO perspective rather than the datastore perspective. JDO determines which objects are embedded independently of the datastore architecture. All of the objects of the supported system classes are embedded objects. JDO manages embedded objects as dependent objects of the application data object that refers to them. As a result, when the application data object is deleted, the persistent state corresponding to the embedded objects is deleted as well.

The JDO specification discusses the possibility of designating some application data objects as embedded within other first class application data objects. In essence, this is intended to be a way for the application to define a second class object. Although the concept is in the specification, it is not well defined by either the 1.0 or 1.0.1 specification. Any behavior documented by a particular JDO implementation may be implementation dependent.

Leaving aside the possibility of embedding an application data object, the only difference between second class objects and embedded objects comes down to the case of those datastore architectures that store the objects of some supported system classes as first class objects rather than as second class objects. For some types of object databases, this situation arises for the collection classes. In this case, the JDO implementation must take special steps to enforce the JDO requirement for the dependency of embedded objects. Likewise, if you disregard the possibility of embedding an application data object, then all application data objects are first class objects.

Embedded objects never have a JDO identity, and they cannot be fetched independently of the application data object that refers to them. Queries return first class application data objects, not embedded objects, in their results. Embedded objects are never members of a JDO extent.

An embedded object participates in a transaction only when the first class application data object that refers to it has joined the transaction. All persistence services for an embedded object are implicit and result from actions that occur on the application data object that refers to it. Embedded objects are always inserted into the datastore, deleted from the datastore, or retrieved from the datastore as a result of the corresponding action on a first class application data object. JDO treats the relationship between a first class application data object and the embedded object that it refers to as a containment relationship. When the application deletes an application data object, the embedded objects that it refers to are also deleted.

JDO offers excellent support for the supported system classes in its query language. Query filters can use the persistent fields whose types are the supported system classes. Chapter 2 describes JDO's query language.

Although it is possible for the application to chain embedded objects, as for example when a HashSet contains a set of Date objects, JDO does not mandate support for chaining embedded objects.

In summary, persistence-capable classes divide into two types, the application data classes and the various system classes that the JDO implementation supports. JDO always manages the objects of the supported system classes as embedded objects. In the JDO metadata, they must be marked either explicitly or by default as embedded. Chapter 5 discusses the JDO metadata.

Replacement and Sharing of Embedded Objects

From time to time, JDO changes the Java object that represents the embedded object's persistent state. Therefore the application should expect that the object identity of the embedded object may change. After completing a transaction or making an object persistent, affected application data objects may refer to different but equivalent embedded objects. When comparing embedded objects, the application should use Java object equivalence (the equals method) rather than Java object identity (the == operator).

JDO does not support sharing embedded objects among first class application data objects. Although the application may assign an embedded object to the persistent field of multiple application data objects, JDO's actions almost never create shared embedded objects. When JDO creates or replaces the embedded objects that an application data object refers to, each application data object will usually refer to its own embedded object. For example, when embedded objects are shared, as shown in Figure 1-2, JDO does not generally store the relationship in the datastore.

click to expand
Figure 1-2: Transient relationship in memory created by the application

Instead, when JDO later retrieves the state of the two application data objects and the embedded objects that they contain, it typically creates the relationships shown in Figure 1-3. As you can see, instead of one shared embedded object, JDO creates two unshared embedded objects. As a result, applications should never rely on application data objects sharing one embedded object.

click to expand
Figure 1-3: The relationship re-created in memory by JDO

As mentioned earlier, some datastores will store the objects of some supported system classes as first class objects. For these datastores, if the application data objects share embedded objects of this type, it is possible that the JDO implementation may not undo the sharing. In this case, when the application data classes share one embedded object as shown in Figure 1-2, JDO may re-create in memory the same relationship when the objects are later retrieved. The application cannot rely on the general rule that shared embedded objects are not shared in the datastore and that JDO will not re-create a shared relationship in memory upon later retrieval.

As a general rule, sharing embedded objects is harmless only when the supported system class is immutable and the application uses Java equivalence to compare two embedded objects. The application should always avoid sharing mutable embedded objects. It is possible that a future version of JDO may prohibit the sharing of mutable embedded objects.

Change Tracking in Supported System Classes

Embedded objects have the responsibility to notify the first class application data object that refers to them when they have changed and to track their own changes, but JDO permits supported system classes to duck this responsibility in some cases. When the supported system class is an immutable type, such as Integer or String, then there is no way for the objects of that type to change. Consequently, there is no need for the immutable system classes to support change notification or tracking.

When the supported system class is a mutable type such as a Date or HashSet, then one of two situations arise. In the first case, the application creates the mutable object and assigns it to the persistent field. Because of the assignment, JDO receives all the notification that it needs that the field's value has changed. In this case, the objects of supported mutable system types do not notify their containing application data objects when they change.

There is one case where the embedded object of a mutable supported system class must notify its containing application data class of any changes made to it. After JDO creates the mutable embedded object to hold the persistent state that it reads from the datastore, any change to the embedded object must cause a notification to the containing application data object. The application data object needs this notification because JDO manages transactions through application data objects. How will this notification occur? Certainly, the Java collection classes, like HashSet, do not contain the logic to notify. Instead, when JDO created the object to hold the state, it did not create an instance of the supported system class, but rather an instance of a derived class of the system class. The JDO implementation supplies these derived classes to implement change notification, change tracking, and other features.

JDO's use of classes derived from the supported mutable system classes is transparent to the application. Their use has no impact on the application's logic. Applications are free to use the instances of the supported system classes whenever they like.

Arrays

Support for arrays is an optional feature of the JDO implementation. Arrays are embedded objects in JDO and are usually stored as second class objects in the datastore. JDO imposes several limitations on arrays that it does not impose on the other supported system classes. JDO does not support the use of arrays in its query language. Although implementations may support change notification, JDO does not require that implementations support change notification for arrays. Consequently, any portable application that uses arrays must take responsibility for informing the referring application data object when the array is modified. (The makeDirty method in the JDOHelper class, described in Chapter 7, handles this task.) When arrays are supported, the implementation decides what type of array elements it supports. It may support arrays of primitives, arrays of application data objects, arrays of other supported system data objects, arrays of arrays, or any combination thereof.

Unmanaged Data Objects

At runtime, for various reasons, JDO may not manage all the objects of persistence-capable classes. Unmanaged objects of persistence-capable classes come into existence in a variety of ways.

  • They may be newly created by the application.

  • An application data object can stop referring to an embedded object, making the embedded object unmanaged.

  • JDO allows the application to explicitly make any managed application data object unmanaged by calling the persistence manager's makeTransient method.

  • The application will obtain only unmanaged objects through serialization. When a managed data object is serialized, the deserialized data object is unmanaged.

  • A clone of a managed data object will be unmanaged.

While data objects may be managed or unmanaged, JDO never manages the objects of classes that are not persistence capable.

An unmanaged object is called a transient object in the JDO specification. Unfortunately, the specification uses the term transient in two different but related ways. On the one hand, a transient object is an object that JDO is not managing at all, and on the other hand, it is a data object that JDO manages transactionally but not persistently. The confusion is compounded by the Java keyword transient, which has nothing to do with JDO.

To reduce confusion, this book follows three conventions:

  • A transient data object is an object of a persistence-capable class that JDO is not managing persistently. JDO may, but usually does not, manage a transient data object transactionally.

  • An unmanaged object may or may not be a data object, but in either case, JDO is not managing it persistently nor transactionally.

  • The specification uses the term transient to name one of the ten management states that a data object may be in. The next section of this chapter describes management states. In this book, the term transient is never used in this sense. Instead, the term JDO-transient is used to name the management state that the specification calls transient. In this book, the term unmanaged object is a synonym for JDO-transient object.

Finally, Java serialization is orthogonal to JDO's management of data objects. You may define application data classes that implement, or do not implement, the Serializable interface. You may define persistent, transactional, and unmanaged fields that are, or are not, transient fields. Chapter 5 describes JDO's interaction with Java's serialization mechanisms in detail.

An important design principle followed by JDO is that unmanaged objects behave in exactly the same way as the object would behave if JDO were not present at all. There are only a few places where the unmanaged objects of an enhanced class differ in behavior from the objects of the unenhanced class. Chapter 5 covers the impacts of enhancement.

start sidebar
Defining Core Terminology

Here are some fundamental definitions for this chapter and the remainder of the book:

  • Application data class: A class defined by the application programmer primarily to hold data that will be stored in the datastore.

  • Application data object: An instance of an application data class.

  • PersistenceCapable class: Synonym for an application data class. This term stresses the fact that application data classes after enhancement implement JDO's PersistenceCapable interface.

  • Persistence-capable class: Either a PersistenceCapable class or one of the classes from the Java standard packages that the JDO implementation supports.

  • Data object: An instance of a persistence-capable class. A data object may be unmanaged, managed, transient, persistent, transactional, transient and transactional, persistent and nontransactional, or persistent and transactional. It may be stored as a first class object or as a second class object. The JDO specification uses the term JDO instance instead of data object.

  • Persistent object: A data object when JDO is managing it persistently.

  • Transactional object: A data object when JDO is managing it transactionally.

  • Managed object: A persistent, transactional, or persistent and transactional data object.

  • Transient object: Any object that JDO is not managing persistently. The JDO specification also uses the term as a synonym for an unmanaged object.

  • JDO-transient: The management state that indicates that JDO is not managing the object at all. The specification calls this the transient state.

  • Unmanaged object: Any object that JDO is not managing either transactionally or persistently. The term unmanaged object is a synonym for JDO-transient object.

  • First class object: A data object that is stored independently in the datastore with a JDO identity. In JDO, application data objects are usually first class objects.

  • Second class object: A data object that is stored in the datastore as part of a first class object. In JDO, objects of the supported system classes, such as String, Date, Long, and HashSet, are usually second class objects.

  • Identity value: The value of an attribute, or a list of attributes, that uniquely identifies one persistent state in the datastore.

  • JDO identity: An object that contains the identity value and can be used to obtain the corresponding application data object.

  • Identity string: The string obtained from the toString method of a JDO identity object. This can be used to obtain an equivalent JDO identity object.

end sidebar




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