JPOX
JPOX
 Project  |  Ver 1.1  |  Ver 1.2  |  JDO  |  JPA  |  Guides  |  Tools
1.1 | Preparation | O/R Mapping | Runtime | Extensions | Developer
Persistence
Object Identity
Primary Key Classes

With application identity you are defining which fields of the class are part of the primary key, and you are taking control of the specification of id's to JPOX. Application identity requires a primary key class, and each persistent capable class may define a different class for its primary key, and different persistent capable classes can use the same primary key class, as appropriate. To specify that a class is to use application identity, you add the following to the MetaData for the class.

<class name="MyClass" identity-type="application" objectid-class="MyIdClass">
    <field name="myPrimaryKeyField" primary-key="true"/>
...
</class>
            

That is, specifying the "identity-type" and "objectid-class". The "objectid-class" is the class defining the identity for this class. You then need to define the primary key class.

Single Field Identity

The simplest way of using application identity is using the JDO 2 SingleFieldIdentity . mechanism. This provides a default PrimaryKey for cases where you have a single field that forms the primary key and you don't need to specify the objectid-class. JPOX 1.1 supports this. Let's take an example

public class MyClass
{
    long id;
    String name;
    String description;
    ...
}
 
<class name="MyClass" identity-type="application">
    <field name="id" primary-key="true"/>
    <field name="name"/>
    <field name="description"/>
</class>

As you can see, we have defined our class to use application-identity and haven't specified an objectid-class. We have simply marked one of our fields as being the primary-key. JPOX interprets and will use the builtin "long" type SingleFieldIdentity primary-key class. Nothing more to do! You will, of course, have to give the field a value before persisting the object, either by setting it yourself, or by using a value-strategy on that field.

If you need to create an identity of this form for use in querying via pm.getObjectById() then you can create the identities in the following way

For a "long" type :
javax.jdo.identity.LongIdentity id = new javax.jdo.identity.LongIdentity(myClass, 101);

For a "String" type :
javax.jdo.identity.StringIdentity id = new javax.jdo.identity.StringIdentity(myClass, "ABCD");

We have shown an example above for type "long", but you can also use this for the following

short, Short       - javax.jdo.identity.ShortIdentity
int, Integer       - javax.jdo.identity.IntIdentity
long, Long         - javax.jdo.identity.LongIdentity
String             - javax.jdo.identity.StringIdentity
char, Character    - javax.jdo.identity.CharIdentity
byte, Byte         - javax.jdo.identity.ByteIdentity
java.util.Date     - javax.jdo.identity.ObjectIdentity
java.util.Currency - javax.jdo.identity.ObjectIdentity
java.util.Locale   - javax.jdo.identity.ObjectIdentity


Rules for User-Defined Primary Key classes

If you wish to use application identity and don't want to use the "SingleFieldIdentity" builtin PK classes then you must define a Primary Key class of your own. You can't use classes like java.lang.String, or java.lang.Long directly. You must follow these rules when defining your primary key class.

  • the Primary Key class must be public
  • the Primary Key class must implement Serializable
  • the Primary Key class must have a public no-arg constructor, which might be the default constructor
  • the field types of all non-static fields in the Primary Key class must be serializable, and are recommended to be primitive, String, Date, or Number types
  • all serializable non-static fields in the Primary Key class must be public
  • the names of the non-static fields in the Primary Key class must include the names of the primary key fields in the JDO class, and the types of the common fields must be identical
  • the equals() and hashCode() methods of the Primary Key class must use the value(s) of all the fields corresponding to the primary key fields in the JDO class
  • if the Primary Key class is an inner class, it must be static
  • the Primary Key class must override the toString() method defined in Object, and return a String that can be used as the parameter of a constructor
  • the Primary Key class must provide a String constructor that returns an instance that compares equal to an instance that r eturned that String by the toString() method.
  • the Primary Key class must be only used within a single inheritence tree.
Primary Key Example - Multiple Field

Here's an example of a composite (multiple field) primary key class

public class ComposedIdKey implements Serializable
{
    public String field1;
    public String field2;

    /**
     *  Default constructor.
     */
    public ComposedIdKey ()
    {
    }

    /**
     * String constructor.
     */
    public ComposedIdKey(String value) 
    {
        StringTokenizer token = new StringTokenizer (value, "::");
        //className
        token.nextToken ();
        //field1
        this.field1 = token.nextToken ();
        //field2
        this.field2 = token.nextToken ();
    }

    /**
     * Implementation of equals method.
     */
    public boolean equals(Object obj)
    {
        if (obj == this)
        {
            return true;
        }
        if (!(obj instanceof ComposedIdKey))
        {
            return false;
        }
        ComposedIdKey c=(ComposedIdKey)obj;

        return field1.equals(c.field1) && field2.equals(c.field2);
    }

    /**
     *  Implementation of hashCode method that supports the
     *  equals-hashCode contract.
     */
    public int hashCode ()
    {
        return this.field1.hashCode() ^ this.field2.hashCode();
    }

    /**
     *  Implementation of toString that outputs this object id's PK values.
     */
    public String toString ()
    {
        return this.getClass().getName() + "::"  + this.field1 + "::" + this.field2;
    }
}