Guide  Reference  Contents  Previous  Next  Index
A persistent object is an object that has been assigned a storage location in a federated database. When you commit the transaction in which you create a persistent object, that object's data is saved in the database; the object can then be accessed by other processes. A persistent object continues to exist beyond the duration of the process that creates it. In contrast, a transient object exists only within the memory of the process that creates it; when that process terminates, the transient object ceases to exist.
Only instances of persistence-capable classes can be persistent objects. Each application defines its own persistence-capable classes. In addition, Objectivity for Java includes persistence-capable classes for collections of persistent objects.
If you perform any of these operations on a transient object, that object is made persistent. If you attempt to perform one of these operations on an object whose class is not persistence-capable, a NonPersistentClassException is thrown.
Container classes are themselves persistence-capable. A container is both a storage object and a persistent object; you can name a container, reference a container in a persistent field of another persistent object, add a container to a persistent collection, and establish a relationship from a persistent object to a container. You can define your own container classes if you need to create containers that have persistent data or relationships; however, most applications have no need to define their own container classes.
When you use the new operator to create an object of a persistence-capable class, the newly created object is transient. On the other hand, when you create an object by copying (using the persistent operation copy, not the Java clone method), an existing persistent object, the new copy is made persistent automatically. This section explains how to make a transient object persistent; "Copying a Persistent Object" explains how to copy an object, creating a new object that is automatically persistent.
You can make a transient object persistent only while a session is in a transaction; the newly persistent object belongs to that session. When you make an object persistent, the corresponding persistent object is created in the federated database. When you commit or checkpoint the transaction, the object is made visible to other clients. If you abort the transaction, the object in memory reverts to being transient and the new persistent object is removed from the federated database.
There are many ways to cause a transient object to be made persistent. Some actions make an object persistent immediately; others cause it to be made persistent when you commit or checkpoint the transaction.
Any of the following actions will make a transient object become persistent immediately:
You can also make a transient object persistent by referencing it in a persistent field of a persistent object. The referenced object is not made persistent immediately: it only becomes persistent when the referencing object is written to a database. The referencing object is written to a database when you commit or checkpoint the transaction in which you made the object persistent or modified the object's persistent fields. Thus a transient object referenced by a persistent object is made persistent when you commit or checkpoint the transaction in which you created the reference between the persistent and transient object. This process is repeated recursively; if the referenced object references another transient object, that object is also made persistent, and so on. This process is called persistence by reachability. The operations fd.flush, db.flush, cont.flush, and obj.write will also write out any modified objects graph, hence making transient objects persistent.
Making an object persistent assigns it to a storage location in the federated database. Making a basic object persistent assigns it a location in a particular container; making a container persistent assigns it a location in a particular database.
The assignment of a basic object to a container, or a container to a database, can be either explicit or implicit.
For guidelines on deciding where to store your persistent objects, see "Assigning Objects to Databases" and "Assigning Basic Objects to Containers".
The following figure illustrates what happens to a basic object's persistent data during the transaction that makes it persistent. A transient object can be created either during a transaction or outside a transaction; in this example the object is created before the start of the transaction that makes it persistent. When an object becomes persistent, the database is informed which container the new object has been assigned to. The database locks that container for read/write access by the session that owns the newly persistent object. Note, however, that the object's persistent data (that is, the values in its persistent fields) is not written to the database. You can think of the database as having an empty object in the specified container.
A new persistent object is first written to the database when you commit or checkpoint the transaction. If the transaction is aborted before the object is written to the database, the corresponding empty object is removed from the database and the object in memory becomes transient again.
Committing a transaction writes the object's persistent data to the database and releases all the session's locks. The object in memory continues to be the session's local representation of the persistent object. The persistent object itself resides in the database and can be shared by other clients, including other sessions of the same application and other applications written in Java, C++, or Smalltalk. Each client has its own local representation of the persistent object.
After the transaction is committed, its session's local representation of a persistent object is not guaranteed to have the same persistent data as the corresponding object stored in the database. A different client may modify the object while the original session is outside a transaction, making the original session's local representation of the object obsolete.
A session can work with a persistent object once all the following conditions have been satisfied:
If a particular operation does not require access to the object's data (the actual values of its field members), you need not fetch the data. In Objectivity for Java, no persistent operations require doing a fetch. For example, deleting, binding, looking up scope names, linking, and moving do not require a fetch prior to execution.
You need to fetch data of objects of application-defined classes only. Remember that an object's persistent data is the values in its persistent fields, and persistent fields are always defined by the application. A class that is part of the Objectivity for Java interface (such as ooMap or ooContObj) has no persistent fields, so objects of those classes do not have persistent data and hence never require fetch() or markModified().
Once these four conditions are met, you can perform any operation that is consistent with the session's lock on the object. For example, if the object is locked for read, you can look at its persistent data or copy it. If the object is locked for write, you can modify, move, or delete it. Any deletions or changes to an object's persistent data exist only in the application's memory until you commit or checkpoint the transaction; then the changes are written to the database.
When you commit or abort a transaction, the session releases all locks obtained during the transaction. The local representation is still owned by the session, and can be reused in subsequent transactions. Note, however, that if another client has deleted the object while your application was between transactions, an exception is thrown the next time you try to perform an operation on the object, pass the object as an argument to other persistent operations, or try to write it out either directly or from a retrieve from another persistent object.
When a transaction ends, all persistent objects that were made persistent or whose data was fetched during the transaction are marked as needing to have their data fetched. As long as the session is outside a transaction, those objects are not guaranteed to have persistent data consistent with the database, because a different client may have modified them. To ensure that you have access to the most recent version of an object's persistent data, you must start a transaction and fetch the object's data again.
If your application uses multiple session objects, remember that each persistent object, storage object, and ODMG transaction object in the application's memory belongs to a particular session. A newly created persistent object belongs to the session that was in a transaction when it was made persistent. A previously existing persistent object belongs to the session that was in a transaction when the object was retrieved from the database.
Objectivity for Java does not allow a persistent object that belongs to one session to interact with objects that belong to another session. For example, if Session1 owns a particular database and Session2 owns a particular basic object, you may not make that basic object a named root in that database. Instead, you must retrieve the same basic object while Session2 is in a transaction. You can then make the newly retrieved basic object a named root in the database because both the newly retrieved object and the database belong to Session2. For additional information, see "Object Isolation".
When you retrieve a persistent object from a database, Objectivity for Java creates an object in the application's memory that represents the object stored in the database. The newly created object has no persistent data; you must explicitly fetch the object's data from the federated database to the local representation. Once you have done so, you can access the data in the object's persistent fields just as you would access the fields of any Java object.
Although the object in memory is called a "persistent object," it is important to remember that the persistent object actually resides in the database. The object in memory is just the session's local representation of the persistent object.
Several methods allow you to retrieve objects from the database. Some of these methods retrieve an individual object, for example, by looking up its root name or its name in the scope of a particular scope object. Other methods return an iterator that finds a number of similar objects, for example, all basic objects of a given class that are stored in a given container. For more information about these methods, see Chapter 11, "Retrieving Persistent Objects".
Every session maintains a cache of the persistent objects that belong to it (including internal persistent objects). The cache ensures that the session has a single object in Java memory representing any particular persistent object that is accessed while the session is in a transaction. When the session is in a transaction, if two different method calls look up the same persistent object, the first method call retrieves the object from the database and returns a local representation for it; the second call returns the local representation created by the first call. For additional information, see "Object Identity".
A particular object remains in the cache until any of the following actions occur:
When multiple processes run concurrently and access the same objects, there is a possibility that the cached information will become stale if you hold a reference for an object after committing or aborting the transaction in which it was retrieved. See "Avoiding Stale Cache Information".
Locking an object informs Objectivity/DB how you plan to use that object. The lock you obtain while one session is in a transaction prevents other sessions and other applications from taking actions that would interfere with your intended use of the object.
A session can lock a persistent object either for read-only access or for read/write access.
Containers are the fundamental unit of locking; when a session locks a basic object, the session implicitly obtains a lock on the object's container. When a session locks a container, the session implicitly obtains locks on all basic objects in the container.
See Chapter 4, "Locking and Concurrency," for a description of MROW and non-MROW transactions and for further details about locking.
You usually don't need to make an explicit call to lock a persistent object. Built-in methods that require a persistent object to be locked will try to obtain the necessary lock. For example, you cannot fetch an object's persistent data unless the session has a read lock on the object; the fetch method obtains the necessary lock before it fetches the data.
If a method is unable to obtain a lock, it will throw a LockNotGrantedException. You can reserve locks in advance of when you need them with the lock method.
If an object's class has field access methods to ensure that its persistent fields are used safely, the methods to get and set the value of a persistent field will automatically lock the object for you. See "Field Access Methods".
Once your session obtains a lock, it typically retains the lock until the transaction is committed or aborted.
After you obtain a lock, you can modify it in the following ways during the transaction:
Fetching an object's data locks the object, if necessary, and transfers the object's persistent data from the federated database to the persistent fields of the local representation. Once you have fetched an object's data, you can access the data in the object's persistent fields just as you would access the fields of any Java object. If a persistent field references a persistent object that has not already been retrieved, fetching the field's data retrieves the referenced object but does not fetch that object's data; thus, the field is set to reference an empty object. A referenced object's data must be fetched independently.
Once you fetch an object's data, it typically remains locked with its data up to date until the transaction is either committed or aborted.
You must call an object's fetch method to fetch its data; Objectivity/DB never automatically fetches persistent data. However, if the object's class has field access methods to ensure that its persistent fields are used safely, the method to get the value of a persistent field will fetch the object's data; see "Field Access Methods". There is no performance overhead for making multiple calls to an object's fetch method; if the data in memory is up to date, the method does nothing.
Before you change the persistent data of a persistent object, you should obtain a write lock on the object and fetch its data. To do so, you should call the object's markModified method; in addition to locking the object's container and fetching its data, this method marks the object as modified. When you commit or checkpoint the transaction, any persistent objects that have been marked as modified will be written to the database; your changes to the object are then available to other processes.
If the object's class has field access methods to ensure that its persistent fields are used safely, the method to set the value of a persistent field will call markModified for you. See "Field Access Methods".
The following figure illustrates what happens to a basic object's data during a transaction that modifies it. Any changes to an object's persistent data exist only in the application's memory until you commit or checkpoint the transaction; then the changes are written to the database.
To create a new persistent object with the same persistent data as an existing persistent object, call the copy method of the existing object. You can copy basic objects only, not containers.
If the object you are copying is marked modified, it is written to the federated database (but is not committed) before the copy operation begins. The operation is performed in the federated database, not in memory. That is, a new persistent object is created in the federated database; the copy method specifies the database, container, or basic object with which to cluster the new object. Persistent data is copied from the existing object in the federated database to the new object in the federated database; see "Copying the Object's Fields". Relationships of the existing object are copied or not, as specified by the definition of each relationship; see "Copying the Object's Relationships". The copy method returns a local representation of the new object; the returned object is persistent, locked for write, and empty. You must fetch its persistent data if you want to examine or modify that data.
When you commit or checkpoint the transaction in which you copy an object, the new copy is made visible to other clients. If you abort the transaction, the new copy is removed from the federated database and the new copy in memory becomes a dead object.
The copy method copies the persistent object stored in the database rather than the session's local representation of that object. In fact, the local representation of the original object does not need to have its persistent data in memory. Because the database contains only persistent data, any transient fields are not affected by the copy operation.
The copy method creates a shallow copy of the original persistent object. Each field of a shallow copy contains exactly the same value as the corresponding field of the original object. If the original object contains a reference to an array or an object in a persistent field, the shallow copy contains a reference to the same array or object in its corresponding field. In contrast, each field of a deep copy contains a copy of the value in the corresponding field of the original object. If the original object contains a reference to an array or an object in a persistent field, the deep copy contains a reference to a deep copy of the array or object in its corresponding field.
Your application may need to implement a mechanism for copying a persistent object with its transient data or for creating a deep copy of a persistent object. If so, you should implement your customized copy mechanism as follows:
If the object being copied has relationships to other objects, the definition of each relationship specifies how the relationship is handled. When a relationship is created, its copy behavior is specified with one of the following constants (defined in the Relationship class):
The following figure illustrates the result of copying an object with a relationship using each of the three copy modes.
At some point you may decide that you need to reallocate objects to a different container configuration. For example, you may want to increase the number of containers to achieve greater concurrency. Objectivity for Java supports moving a persistent basic object to a new container with the move method.
The move method requires that you specify the database, container, or basic object that you want the moved object to be near. The following table summarizes where a basic object is stored for any given near object.
After a successful move, the object has a new object identifier, and the local representation of the object references the new basic object. If the move is unsuccessful, the identifier is unchanged and the local representation remains valid and still references the original object.
If you abort the session after moving an object:
If the moved object is referenced from a unidirectional relationship of another object, you must drop a to-one relationship or remove a to-many relationship before the move and then form a to-one relationship or add a to-many relationship after the move. For information on how to work with relationships, see "Accessing Relationships". On the other hand, if the moved object has bidirectional relationships with other objects, Objectivity/DB updates any references to the object.
You should not move an object that is used in a persistent collection:
If you need to move such an object, you must first temporarily remove the appropriate element(s) from all affected persistent collection(s). After the move is successfully completed, you can add the removed element(s) back to the collection(s).
Objectivity for Java uses name maps to store root names. As a consequence, the recommendations and warnings concerning moving objects referenced in a persistent collection apply also to named roots. To prevent possible corruption of a root dictionary and any objects it references, you must unbind a root name before you move the object, and bind the object after the move. See "Named Roots" for information on how to work with named roots.
An object that is a scope object or is scoped by other objects will lose that scope when the object is moved. This will not compromise data integrity in any way. However, any moved object will need to reestablish scope-to or scope-by any objects after the move.
To preserve the moved object as a name scope, you must:
To preserve all the scope names of a moved object you must:
See "Name Scopes" for further information on how to work with scope named objects.
A predicate scan using an index that references a moved object will yield undefined results. In contrast to relationships, name maps, and scopes, it is not possible to delete a reference to an individual object from an index. Therefore, you must delete the entire index before moving an object that is referenced by the index and recreate the index after the object is moved. See "Working With an Index" for information on how to delete and recreate an index.
Deleting a persistent object removes the object from the database when the transaction commits. Deleting a persistent object deletes any association links from the deleted object to destination objects. Furthermore, if any of the associations is bidirectional, the inverse link to the deleted object is removed from each destination object to maintain referential integrity. However, if another persistent object references the deleted object through a unidirectional association or directly in one of its attribute data members, you are responsible for removing that reference.
To delete a basic object, retrieve the object from the database and call its delete or deleteNoProp method. To delete a container and all its objects, get a local representation of the container, and call its delete or deleteNoProp method.
The delete methods propagate the deletion operation along relationships for which deletion propagation is enabled.
When you use the delete method to delete a persistent object that has relationships for which delete propagation is enabled, you also delete the destination objects linked by those relationships. If you want to delete a source object without deleting its destination objects, you should call its deleteNoProp method instead.
The session's local representations of deleted objects are converted to dead objects. When you commit or checkpoint the transaction, the objects are physically removed from the federated database. If the transaction is aborted, the objects are not removed from the federated database.
The following figure illustrates a transaction in which a basic object is deleted.
Deleting an object deletes that object alone, not any objects referenced by the object's fields. If the object is stored in a garbage-collectible container, its referenced objects will become available for garbage collection if no other object references them. If you store a graph of related objects in a non-garbage-collectible container, however, you must take explicit action if you want to delete the entire graph of objects. You must traverse the graph and explicitly delete each object. In addition, you should explicitly delete any referenced internal persistent objects. "Container Types" explains the difference between garbage-collectible and non-garbage-collectible containers.
A deleted object is removed from any bidirectional relationships in which it is involved. However, if another persistent object references the deleted object in a unidirectional relationship or directly in one of its persistent fields, you are responsible for removing that reference. An exception is thrown if you attempt to write a persistent object that references a dead object.
You should not delete an object used in a persistent collection:
If you need to delete such an object, you must first remove the appropriate element(s) from all affected persistent collections.
Each session maintains a cache of the objects that belong to it. You typically do not need to be concerned about the state of the information in the cache. In a concurrent environment, however, multiple processes may run simultaneously, each creating, moving, and deleting objects of the same class. Situations can arise in which the actions of one process render the cache in another process "stale."
Within the cache, objects are organized by their object identifiers (OIDs). Any method that looks up a persistent object gets the object's OID from the federated database and checks the session's cache for that OID. If the OID is not in the cache, the persistent object is retrieved from the database; otherwise the persistent object is obtained directly from the cache.
At the end of the transaction in which a persistent object is retrieved from the database, your application gives up its lock on the object, permitting other processes to access the object. If your application holds a reference to the object, the Java garbage collector cannot remove the object's data from the session's cache. If another process then moves or deletes the object, the cached information becomes stale. The cache continues to identify the object by its original OID, which is now invalid:
The situation is complicated by the fact that Objectivity/DB reuses OIDs that have become invalid. If an invalid OID in the cache is reassigned to a different object, your application will use the OID thinking that it identifies one object when it actually identifies a different object--possibly an object of a different class. For example, if your application performs an operation that obtains the reassigned OID, it will not retrieve the correct object from the database but will instead use the cached object.
If the OID has been reassigned to an object of a different class, the cached type number for the OID will identify the class of the deleted or moved object, whereas the type number for the OID in the database will identify the class of the object to which the OID is now assigned.
Three problems can arise when you access an object with stale cache information:
If you try to access an object whose OID is now unassigned, an ObjyRuntimeException is thrown, indicating that the object does not exist in the database.
If you detect this situation, you can remove the stale cached information in either of two ways:
If the OID for a moved or deleted object is assigned to a different object of the same class, your application may use the cached object inappropriately instead of retrieving the new object. Although there is no way to detect that an object's OID has been assigned to a different object of the same class, your application may find that the object's data appears inconsistent.
Objectivity/DB protects against database corruption in the case that you make changes to the cached object and try to save it. If you attempt to write the object whose cached information is stale, its data is fetched first, which will bring the correct data into the Java object. If the object was moved or deleted and its OID reassigned, you will write the new object, thinking that it is writing the old (deleted or moved) object.
The same problem arises if an object X has a field that references an object Y and Y's OID is reassigned to an object of the same class; X will still have a valid reference, but to the wrong object.
Because these problems are undetectable, if your application runs in a multiprocessing environment in which applications may be moving or deleting objects, the safest programming practice is to drop all object references at the end of every transaction.
If the OID for a moved or deleted object is assigned to a different object of a different class, your application may use the cached object inappropriately instead of retrieving the new object. In this case, two exceptions may be thrown:
A ClassCastException doesn't always indicate that your application is using a persistent object with stale cache information. This exception is also thrown in other, unrelated, cases in which you try to cast a Java object to an illegal type.
This exception is also thrown if you try to get a referenced or related object whose cached type number does not match the type number in the database.
If you detect that a particular object has stale cached information, you have two alternatives. You can reload the cache, obtaining a reference to the new object that uses the old object's OID, or you can drop the object's cached information.
The decision whether to get a new object reference or drop the cached information depends on the specifics of your application. For example, suppose you perform a scan operation that retrieves an object that does not match its cached information. In that case, you should reload the cache so that you can get the new object that matches the scan criteria. On the other hand, suppose that object X references object Y. If Y has been deleted by another process and it's OID reused by an object of a different class, you should drop the cached information for Y and remove X's reference to the new object.
You can reload the object calling the reloadCachedObject method of the object's session. This method removes the old object's cached information, making it a dead object; it then retrieves and returns the new persistent object that uses the old object's OID and caches up-to-date information about the new object.
ExampleThis transaction gets all objects from a particular container and tries to cast each one to the SimpleClassWithField class. If the cast fails, the cache has stale information about an object of a different class that used to have the same OID. In that case, the code reloads the object and casts it to SimpleClassWithField.
session.begin(); System.out.println("getting iterator..."); Iterator itr = cont.contains(); SimpleClassWithField scwf = null; int count = 0; while (itr.hasNext()) { Object o = itr.next(); // Retrieve generic Object try { scwf = (SimpleClassWithField) o; // Try the cast } catch (ClassCastException e) { // Cast didn't work, reload the object scwf = (SimpleClassWithField) session.reloadCachedObject(o); } System.out.println("Got " + scwf.toString()); count++; } System.out.println("count of objects: " + count); session.commit();
You can drop the object's cached information and make it a dead object by calling the dropCachedObject method of the object's session.
ExampleThis transaction scans for all objects of the SimpleClassWithRef class. It calls the getRef method of each retrieved object to get a referenced object, which should be an instance of SimpleClass. If the referenced object is not of the correct type, it drops that object's cached information and calls the referencing object's setRef method to remove the reference to the deleted or moved object.
session.begin(); System.out.println("getting iterator..."); Iterator itr = cont.scan("test.data.SimpleClassWithRef"); Object o = null; SimpleClassWithRef scwr = null; SimpleClass sc = null; boolean needToCheckRefType = false; int count = 0; while (itr.hasNext()) { scwr = (SimpleClassWithRef) itr.next(); System.out.println("fetching " + scwr.toString()); scwr.fetch(); sc = scwr.getRef(); try { sc.fetch(); } catch (JavaTypeNMismatchException e) { // Get the referenced object as type Object o = session.reloadCachedObject(sc); needToCheckRefType = true; } if (needToCheckRefType) { // Got a JavaTypeNMismatchException needToCheckRefType = false; try { sc = (SimpleClass) o; } catch (ClassCastException e) { // This reference is bad System.out.println( "ClassCastException: " + e.getMessage() + ", setting reference to null"); // Remove the reference scwr.setRef(null); // Remove sc from the cache session.dropCachedObject(sc); } } // If need to check count++; } // While more objects System.out.println("count of objects: " + count); session.commit();
In addition to dropping or reloading cached information for a particular object, you can drop all objects of a particular class from every session's cache or you can drop all objects that belong to a particular session.
If your application detects repeated problems with its cached data, you can try either of the following corrections:
If you want to continue to retrieve or create objects of the class, you must ensure that the schema class description is restored. If the dropped class uses a custom schema class name, after dropping it, you must call the connection object's setSchemaClassName method to reset the schema class name, then call the connection object's registerClass method to retrieve the schema class description from the federated database to the cache.
If problems do not appear to be localized to a small number of classes or a small number of sessions, the best approach is to terminate all sessions in your application and create one or more new sessions for future interactions with the federated database.
When you store a persistent object containing a non-null field of one of the following Java types, an internal persistent object for that field is created in the same container:
java.util.Date java.sql.Date java.sql.Time java.sql.Timestamp
Furthermore, an internal persistent object is created for each element of an array of the following types:
String[] java.util.Date[] java.sql.Date[] java.sql.Time[] java.sql.Timestamp[]
You generally do not need to deal directly with these internal persistent objects, but you need to be aware of their existence in the following circumstances:
If a class has fields that reference internal persistent objects, you can override the move method to move the internal objects along with the referencing object. If move than one object can reference the same internal persistent object, however, you may not want to override move.
The Appointment class has three fields that contain, respectively, a date, an array of times, and a string. This class overrides the move method to move any internal objects referenced by the moved object. Note that the String field announcement does not need to be moved because it does not reference an internal persistent object.
public class Appointment extents ooObj { private java.util.Date scheduledDate; private java.sql.Time availableTimes[]; private String announcement; ... public void move(Object o) { moveReferences(o); super.move(o); } private void moveReferences(Object o) { markModified(); com.objy.db.app.ooFDObj fd = getSession().getFD(); // Move date referenced by shecheduledDate field fd.moveReference(scheduledDate, o); // Move each time in the availableTimes array for (int i=0; i<3; i++) fd.moveReference(availableTimes[i], o); // Move the availableTimes array fd.moveReference(availableTimes, o); } }
If you always store objects of your classes in garbage-collectible containers, you do not need to delete internal persistent objects. When a given internal persistent object cannot be reached from a named root, it will be available for garbage collection. On the other hand, if objects that reference internal persistent objects may be stored in non-garbage-collectible containers, you should take care to delete the internal persistent objects when they are no longer needed. "Container Types" explains the difference between garbage-collectible and non-garbage-collectible containers.
For example, if objects of your class may be stored in non-garbage-collectible containers, and you know that a given internal persistent object can be referenced by at most one other object, you can override the delete and deleteNoProp methods to delete the internal objects along with the referencing object. Your methods should delete:
The Product class has three fields that contain, respectively, a time stamp, an array of long integers, and an array of strings. This class overrides the delete and deleteNoProp methods to delete any internal objects referenced by the deleted object. Note that the elements of the long[] array in the repairCodes field do not need to be deleted, but elements in the String[] array in the notices field do.
public class Product extents ooObj { private java.sql.Timestamp lastUpdated; private long repairCodes[]; private String notices[]; ... public void delete() { deleteReferences(); super.delete(); } public void deleteNoProp() { deleteReferences(); super.deleteNoProp(); } private void deleteReferences() { markModified(); com.objy.db.app.ooFDObj fd = getSession().getFD(); // Delete timestamp referenced by lastUpdated field deleteReference(lastUpdated); // Delete the repairCodes array deleteReference(notices); // Delete each string in the notices array for (int i=0; i<3; i++) { deleteReference(notices[i]); notices[i] = null; } // Delete the notices array deleteReference(notices); } }
A dead object is an object that is no longer valid for Objectivity for Java operations. A persistent object becomes dead when it is deleted or when the session that owns it is terminated.
If the transaction is aborted, an object that was made persistent during the transaction goes back to the transient state; an object that was retrieved remains a dead object. If the object's database was deleted, the object no longer exists in the federated database; however, if the object itself (or its container) was deleted, the object continues to exist in the federated database after the transaction is aborted. The local representation of the object is a dead object, but you may retrieve the object again if you need to work with it.
When a persistent object becomes a dead object, it loses any relationships it had to other objects.
Any operation that you would normally perform on a persistent object is invalid on a dead object; if you attempt such an operation, an ObjectIsDeadException will be thrown. You can call an object's isDead method to test whether it is dead.
After a session is terminated, all the objects that belong to the session will behave like dead objects. Although isDead will return false for these objects, an ObjectIsDeadException will be thrown if you attempt to operate on them.
Guide  Reference  Contents  Previous  Next  Index