5.2. Object Identity

5.2.1. Datastore Identity
5.2.2. Application Identity
5.2.3. Primary Key Generation Sequence Factory Auto-Increment

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.


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-increment columns. 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.setPrimaryKey (gen.getNext ().longValue ());
pm.makePersistent (pc1);

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

pm.currentTransaction ().commit (); 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.

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

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!