There are a few advanced identity topics, which we will consider in this section.
If you are not mapping your JDO object model onto an existing relational schema and you are using an implementation that supports both datastore and application identity, you frequently have the freedom to choose the form of identity. Datastore identity is the logical choice if there is not a natural primary key to identify instances of the class. It is also useful if you prefer to have the JDO implementation generate a unique identity value. Datastore identity also requires less development work on your part. But for some entities being modeled, a primary key is the most suitable solution because of a natural primary-key value that is used to identify the data.
The primary difference between datastore and application identity in your persistent class is the need to define equals( ) and hashCode( ) methods for your persistent classes that use application identity. The only other difference is the specification of the identity type in your metadata. You can develop a persistent class and define an application identity class for it, but then in the metadata you could switch between datastore and application identity. If you do change the identity in the metadata, you need to enhance your classes again, as the enhanced class contains identity-specific information.
If you want to have the flexibility of changing the type of identity used for a persistent class, you should insulate your applications from the particular identity type you choose. When you access an instance with application identity, you initialize an instance of the application identity class with values for the primary-key fields and call getObjectById( ).
As an alternative to getObjectById( ), you could execute a Query, where the filter tests the equality of query parameters with fields in the class. Such a query will work regardless of whether the class uses datastore or application identity. You could define a method for this purpose, possibly a static method of your persistent class. It would have a parameter for each field needed to identify an instance and the PersistenceManager to use. Internally, the method could issue a query, or, if you eventually decide to use application identity, it could call getObjectById( ). Be aware, though, that calling getObjectById( ) will likely perform better than a query.
Under some circumstances, you can use identity instances across different PersistenceManager instances from the same or different implementations. For example, when using multiple PersistenceManager instances retrieved from the same PersistenceManagerFactory, you can use the following code to get an instance in a PersistenceManager (referenced by the pm variable) with the same identity as an instance from a different PersistenceManager:
pm.getObjectById(JDOHelper.getObjectId(obj), validate);
If multiple PersistenceManager instances (which have been returned by the same PersistenceManagerFactory instance) have their own copy of the same persistent instance in their cache, all the identity instances that are returned by calls to getObjectId( ) return true to equals( ), since they all refer to the same persistent object, even though the identity instances were acquired from distinct copies of the same persistent instance.
You can use getObjectById( ) only for instances of persistent classes using application identity when you are working with PersistenceManager instances of different JDO implementations. Since each implementation has its own representation for datastore identity, you cannot pass a datastore identity value from one implementation to a PersistenceManager of a different implementation in a call to getObjectById( ).