While a persistent instance is in memory, it transitions through certain lifecycle events, as we described in Chapter 11. You may want to execute some functionality when these events occur. For example, if you have a persistent class with nonpersistent fields, you may want to initialize the values of the fields when instances from the datastore are instantiated in memory. This is enabled in JDO by a mechanism called an instance callback.
JDO defines the InstanceCallbacks interface to support instance callbacks. This interface has four methods, each of which is called when a particular lifecycle event occurs. If you declare that a persistent class implements the InstanceCallbacks interface, the following methods must be defined and are called when their associated lifecyle event occurs:
Called for an instance after the values have been loaded into its default fetch group fields. This occurs when the instances transition from hollow to persistent-clean or persistent-dirty. In this method, you should initialize nonpersistent fields that depend on fields in the default fetch group. Another use for this method is to register it with other objects in the runtime environment.
The enhancer does not add field mediation code to this method; so, you should access only fields in the default fetch group, since you are not guaranteed that the other fields have been fetched. The context in which jdoPostLoad( ) is called does not allow access to other persistent instances.
Called before the field values of persistent-new and persistent-dirty instances are flushed to the datastore during commit or to perform a query in the datastore server. It is not called for instances being deleted, which are in the persistent-deleted or persistent-new-deleted state. If you want the stored value for a persistent field to be based on the value of another field that is not persistent, you should set the persistent field's value in this method. The enhancer modifies this method so that the changes you make to persistent fields are propagated to the datastore. You can also access the instance's PersistenceManager and other persistent instances in the method.
Called before an instance's persistent fields are cleared (set to their Java default value). This occurs during commit when persistent-new, persistent-clean, and persistent-dirty instances transition to the hollow state. In this method, you should clear nonpersistent fields, nontransactional fields, and associations that exist between the instance and other objects in the runtime environment. The enhancer does not add the field-mediation code to this method, and you can access only transient, transactional, and default fetch group fields.
Called during the execution of deletePersistent( ) for an instance, before the state of the instance transitions to persistent-deleted or persistent-new-deleted. The enhancer adds the field-mediation code to this method, so you can access all the fields. But once this method completes, you can no longer access the fields. In Chapter 8, we described the use of this method to implement a composite-aggregation association, which would propagate the deletion to existence-dependent instances. This is also referred to as a cascading delete.
You can use jdoPostLoad( ) and jdoPreClear( ) in concert to establish and remove relationships between your persistent instances and transient instances in the application environment as the persistent instances enter and leave the cache. The jdoPostLoad( ) method could initialize a transient field to some transient instance in the application, which could also reference the persistent instance. In jdoPreClear( ), you could remove the reference to the persistent instance held by the transient instance.