5.2. Object Identity
Prev | Chapter 5. Persistent Classes | Next

## 5.2. Object Identity

Kodo supports both datastore and application JDO identity types (see Section 4.5, “JDO Identity” in the JDO Overview for a refresher on JDO identity types).

### 5.2.1. Datastore Identity

For datastore identity, Kodo uses the public `kodo.util.Id` class. You can manipulate datastore oid values returned by Kodo JDO by casting them to this class. You can also create your own `Id` instances and pass them to any Kodo JDO method that expects a datastore oid object. Remember, however, that datastore identity in JDO is meant to be opaque; if you find yourself having to use the `Id` API often, it may be a sign that you should be using application identity.

### 5.2.2. Application Identity

If you choose to use application identity, you may want to take advantage of Kodo JDO's application identity tool. The application identity tool generates Java code implementing the object identity class for any persistent type using application identity. The code satisfies all the requirements JDO places on object identity classes. You can use it as-is, or simply use it as a starting point, editing it to meet your needs.

Before you can run the application identity tool on a persistent class, the class must be compiled and must have complete JDO metadata. Set the metadata's `objectid-class` attribute to the desired name of the generated object identity class, and be sure to include `<field>` elements for all primary key fields, with the `primary-key` attribute set to `true`.

The application identity tool can be invoked via the included `appidtool` shell/bat script or via its Java class, `kodo.enhance.ApplicationIdTool`.

Example 5.1. Using the Application Identity Tool

    appidtool package.jdo

The application identity tool accepts the standard set of command-line arguments defined by the configuration framework (see Section 2.3, “Command Line Configuration”), including code formatting flags described in Section 2.3.1, “Code Formatting”. It also accepts the following arguments:

- `-ignoreErrors/-i <true/t | false/f>` : If `false`, an exception will be thrown if the tool is run on any class that does not use application identity, or is not the base class in the inheritance hierarchy (recall that subclasses never define the application identity class; they inherit it from their persistent superclass).

- `-directory/-d <output directory>`: Path to the output directory. If the directory does not match the generated oid class' package, the package structure will be created beneath the directory. If not specified, the tool will first try to find the directory of the `.java` file for the persistence-capable class, and failing that will use the current directory.

Each additional argument to the tool must be one of the following:

- The full name of a persistent class.

- The .java file for a persistent class.

- The `.class` file of a persistent class.

- A `.jdo` metadata file. The tool will run on each class listed in the metadata.

| Note
When running Kodo JDO tools on `.java` files, only the top-level class for the file will be processed. Inner classes are ignored.

### 5.2.3. Primary Key Generation

Kodo supports two styles of primary key generation: sequence factories and auto-identity columns.

#### 5.2.3.1. Sequence Factory

To generate unique datastore identity primary key values, Kodo JDO typically uses a `kodo.jdbc.schema.SequenceFactory` internally. The default sequence factory implementation in use is controlled by the `kodo.jdbc.SequenceFactory` configuration property. You can also declare that a given class uses a specific sequence factory through the `jdbc-sequence-factory` metadata extension.

Using a sequence factory allows coarse-grained control over primary key values while maintaining the simplicity of using datastore identity. Furthermore, it is possible to use the sequence factory yourself to make default assignments to the fields of application identity instances. This gives you the fine-grained control of application identity, without the burden of coming up with your own system to generate unique primary key values.

Kodo JDO ships with four available sequence factories, and you are free to substitute your own as well.

- `db`: This is the default. It is an alias for the `kodo.jdbc.schema.DBSequenceFactory` class. The `DBSequenceFactory` uses a special single-row table to store a global sequence number. If the table does not already exist, the factory will create it the first time you run the mapping tool's refresh action. The `DBSequenceFactory` accepts the following properties:

  - `TableName`: The name of the special sequence number table to use. Defaults to `JDO_SEQUENCE`.

  - `PrimaryKeyColumn`: The name of the primary key column for the sequence table. Defaults to `ID`.

  - `SequenceColumn`: The name of the column that will hold the current sequence value. Defaults to `SEQUENCE_VALUE`.

  - `Increment`: The amount to increment the sequence number by. Defaults to 50, meaning the factory will set aside the next 50 numbers each time it accesses the sequence table, which in turn means it only has to make a database trip to get new sequence numbers once every 50 object inserts.

- `db-class`: This is an alias for the `kodo.jdbc.schema.ClassDBSequenceFactory`, which extends the `DBSequenceFactory` above with the ability to maintain a separate sequence number per-class. It shares the same properties as the `DBSequenceFactory`. Instead of maintaining a global sequence number in a single row, though, this factory's sequence table contains a sequence number for each persistent class, one per row.

- `native`: This is an alias for the `kodo.jdbc.schema.ClassSequenceFactory`. Many databases have a concept of "native sequences" -- a built-in mechanism for obtaining monotonically incrementing numbers. For example, in Oracle, a database sequence can be created with a statement like `CREATE SEQUENCE MYSEQUENCE`. Sequence values can then be atomically obtained and incremented with the statement `SELECT MYSEQUENCE.NEXTVAL FROM DUAL`. Kodo JDO provides support for this common mechanism of primary key generation with the `ClassSequenceFactory`. The factory accepts the following properties:

  - `TableName`: The table name to run sequence queries against. Defaults to `DUAL`.

  - `Format`: The string used to generate the SQL for selecting a sequence value. The string can have two placeholders: {0} for the sequence name and {1} for the table name. The default is `SELECT {0}.NEXTVAL FROM {1}`.

  - `SequenceName`: The name of the default sequence. Defaults to `JDOSEQUENCE`. Each class can also declare what sequence name to use for members of that class through the `jdbc-sequence-name` class-level metadata extension.

- `sjvm`: This is an alias for the `kodo.jdbc.schema.SimpleSequenceFactory`. This factory uses an in-memory static counter, initialized to the current time in milliseconds and monotonically incremented for each new object. It is only suitable for single-JVM environments.

Example 5.2. Sequence Factory Configuration

A hypothetical excerpt from `kodo.properties` to use the `ClassSequenceFactory`.

    kodo.jdbc.SequenceFactory: native(TableName=SEQTABLE, \
        Format="SELECT {0}.NEXT FROM {1}")

As mentioned above, you may want to use the sequence factory in your application. The example below demonstrates how to do so.

Example 5.3. Accessing the Sequence Factory

You may find it useful to access the sequence factory yourself to help create unique application identity field values. You can accomplish this by getting a `SequenceGenerator` instance, which is a delegate to the `SequenceFactory`:

    import kodo.runtime.*;

    ...

    SequenceGenerator gen = KodoHelper.getSequenceGenerator (pm, MyPCClass.class);
    pm.currentTransaction ().begin ();

    MyPCClass pc1 = new MyPCClass ();
    pc1.setPriaryKey (gen.getNext ().longValue ());
    pm.makePersistent (pc1);

    MyPCClass pc2 = new MyPCClass ();
    pc2.setPriaryKey (gen.getNext ().longValue ());
    pm.makePersistent (pc2);

    pm.currentTransaction ().commit ();

#### 5.2.3.2. Auto-Increment

Some databases allow you to define columns that are automatically assigned a unique numeric value when a record is inserted. In many databases, this value is monotonically increasing. Thus, Kodo JDO refers to these columns as auto-increment columns.

Any field can use an auto-increment column in Kodo, but they are most often used for primary key fields under application identity, or for the primary key column under datastore identity. Before you decide to use auto-increment columns, you should be aware of the following restrictions:

1. Auto-increment columns must be an integer or long integer type.

2. Databases support auto-increment columns to varying degrees. Some do not support them at all. Others only allow a single auto-increment column per table, and require that it be the primary key column. More lenient databases may allow non-primary key auto-increment columns, and may allow more than one per table. See your database documentation for details.

3. Statements inserting into tables with auto-increment columns cannot be batched. After each insert, Kodo must go back to the database to retrieve the last inserted auto-increment value to set back in the persistent object. This can have a negative impact on performance.

4. Persistent-new objects using auto-increment columns for their primary keys will not be assigned their final JDO oid until after the persistence manager flushes to the database, as demonstrated by this example.

The jdbc-auto-increment metadata extension controls Kodo's use of auto-increment columns. Placing this extension beneath the `<class>` element indicates that the datastore identity primary key column of the class will auto-increment. Placing it on a <field> element means that the field's column will auto-increment. You must specify these extensions even if you do not use Kodo to create your schema, because Kodo cannot reliably determine which columns are auto-incrementing through the JDBC driver alone.

Example 5.4. Auto-Increment Metadata

In the example below, class `Person` uses an auto-incrmenting datastore identity primary key column, while class `Form` uses an auto-incrementing primary key field with application identity.

    <jdo>
      <package name="com.xyz">
        <class name="Person">
          <extension vendor-name="kodo" key="jdbc-auto-increment" value="true"/>
        </class>
        <class name="Form" objectid-class="FormId">
          <field name="id" primary-key="true">
            <extension vendor-name="kodo" key="jdbc-auto-increment" value="true"/>
          </field>
        </class>
      </package>
    </jdo>

When you use auto-incrementing primary key columns under either datastore or application identity, Kodo is required to do additional work when it flushes your objects to the database. Kodo must ensure that database rows with auto-incrementing primary keys are flushed before rows that need to store those primary keys as part of a foreign key relation (actual or logical). Therefore, if any of your persistent types have relations to classes with auto-incrementing primary key columns, you must set the following configuration property:

    kodo.jdbc.AutoIncrementConstraints: true

If you do not set the above property, Kodo may create invalid database relations.

Example 5.5. Auto-Increment Object Ids

This example shows when you can get the permanent object id for an object with an auto-incrementing primary key.

    Person person = new Person ();
    person.setFirstName ("Abe");
    person.setLastName ("White");

    // when you initially make the object persistent, it has a temporary oid
    pm.currentTransaction ().begin ();
    pm.makePersistent (person);
    Object oid = pm.getObjectId (person);                   // temp oid
    Object toid = pm.getTransactionalObjectId (person);     // same temp oid

    // if you need the permanent oid before commit, you can manually flush; this
    // doesn't change the standard oid value, which JDO says has to stay the
    // same throughout a transaction, but it does make the transactional oid
    // value the final oid
    ((KodoPersistenceManager) pm).flush ();
    oid = pm.getObjectId (person);                          // still temp oid
    toid = pm.getTransactionalObjectId (person);            // permanent oid!

    // or you can wait and get the permanent oid value after commit
    pm.currentTransaction ().commit ();
    oid = pm.getObjectId (person);                          // permanent oid!
    oid = pm.getTransactionalObjectId (person);             // permanent oid!

Prev | Up | Next
Chapter 5. Persistent Classes | Home | 5.3. Mutable Second Class Object Fields