An instance transitions from one lifecycle state to another as the application or JDO implementation performs various operations on it. These state transitions occur during a transaction and at the completion of a transaction. A transition can occur as a result of the passing of an instance as a parameter to a method, such as makePersistent( ). An instance can also transition from one state to another without the application performing any direct operations on the instance. For example, an instance made persistent via reachability changes state without the application directly passing the instance to a method. An instance in the hollow or persistent-clean state will transition to persistent-dirty if it contains a collection field and you add or remove an element from the collection.
Figure 11-1 illustrates the state transitions that occur when you make a call to makePersistent( ) or deletePersistent( ), or when you access a managed field. In the figure, Start State 1 represents the application calling a constructor to create an instance, and Start State 2 occurs when the JDO implementation calls the no-arg constructor to instantiate an instance from the datastore.
If any persistent field of a hollow instance other than a primary-key field is read, the instance transitions to persistent-clean. If a managed field of a hollow or persistent-clean instance is modified, the instance transitions to persistent-dirty. Once an instance enters the persistent-deleted or persistent-new-deleted state during a transaction, no further state transitions occur until transaction completion.
When a transaction completes via a call to commit( ) or rollback( ), instances in every lifecycle state, except hollow and transient, transition to a new lifecycle state; hollow and transient instances remain in their current state. Figure 11-2 illustrates the state transitions that occur when you call commit( ) or rollback( ) and the RetainValues flag is set to false. Chapter 14 covers the behavior that occurs when the RetainValues flag is true.
As illustrated in Figure 11-2, persistent-clean, persistent-dirty, and persistent-new instances transition to hollow at commit. In addition, instances that were persistent at the beginning of the transaction (including those in the hollow, persistent-clean, persistent-dirty, or persistent-deleted state) transition to hollow at rollback, and they retain their identity and association with their PersistenceManager instance.
A persistent-deleted instance transitions to transient at commit. Since it has been deleted from the datastore, it is not associated with a datastore instance. During its transition to the transient state, it loses its identity and association with its PersistenceManager, and its persistent fields are initialized with their Java default values.
A persistent-new-deleted instance transitions to transient at commit and rollback. During these transitions, it also loses its identity and association with its PersistenceManager. When a transaction commits, its persistent fields are initialized with their Java default values.
All instances that transition to transient lose their identity and association with their PersistenceManager, whereas all instances transitioning to hollow retain their identity and association with their PersistenceManager. Primary-key fields are always accessible, regardless of the state of the instance. Read access to these fields is never mediated.
A hollow instance maintains its identity and association with its PersistenceManager instance. Between transactions, the hollow state guarantees that there is a single, unique copy of a persistent instance with a specific identity in the cache. Furthermore, if the application makes a request (via query, navigation, or look up by identity) for the same instance in a subsequent transaction, using the same PersistenceManager instance, the identical Java instance in memory is returned, assuming it has not been garbage-collected.
If the instance's class uses application identity, the primary-key fields are maintained. These fields can be accessed between transactions. If the implementation does not support the NontransactionalRead or NontransactionalWrite optional features, access of any other fields between transactions throws a JDOUserException.