5.2. Object Identity

5.2.1. Datastore Identity
5.2.2. Application Identity
5.2.3. Single Field Identity
5.2.4. Primary Key Generation
5.2.4.1. Sequence Factory
5.2.4.2. Auto-Increment
5.2.4.3. Sequence-Assigned

Kodo supports both datastore and application JDO identity types, including JDO 2's single field application identity (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:

  • -token/-t <token>: The token to use to separate stringified primary key values in the string form of the object id. This option is only used if you have multiple primary key fields. It defaults to "::".

  • -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]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. Single Field Identity

The JDO Overview describes single field identity in Section 4.5.3, “Single Field Identity”. Pay particular attention to the note in this section detailing Kodo's treatment of single field identity as a JDO 2 preview feature. Also, note that until JDO 2 jars are available, using the single field identity preview will introduce Kodo dependencies into your persistent classes during enhancement.

5.2.4. Primary Key Generation

Kodo supports three styles of primary key generation: sequence factories, sequence assigned fields, and auto-increment columns.

5.2.4.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 can also automatically assign values from this sequence factory. See Section 5.2.4.3, “Sequence-Assigned”.

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.

    Using the default settings, the DDL for the sequence table will look like this:

    CREATE TABLE JDO_SEQUENCE(ID TINYINT NOT NULL PRIMARY KEY, SEQUENCE_VALUE BIGINT)
    
  • 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}")

The assigned sequence factory for the class/configuration can be used to assign field values on flush. This is especially useful for generating primary key values in application identity classes. See Section 5.2.4.3, “Sequence-Assigned”.

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 ();

5.2.4.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. Requesting the object id of persistent-new objects using auto-increment columns for their primary keys will cause a flush so that the id can be determined.

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>

5.2.4.3. Sequence-Assigned

Sequence factories can be applied to classes using application identity as well. This is useful for generating unique primary key values automatically. These values will be generated when the owning instance is made persistent. Combined with single field identity, this feature simplifies the use of application identity. This field level extension can be used for any long compatible field (i.e. long, short, integer or their wrapper types).

Kodo will use the same sequence factory assigned to the class to generate the next value. If multiple fields are marked as sequence assigned, Kodo will assign unique values for each field. If a non-default value was already assigned when PersistenceManager.makePersistent () (or implied during persistence by reachability), the field will not be assigned a value.

Example 5.5. Sequence-Assigned Metadata

In this example, class Company will have a single primary key field id. This field's value will be auto-assigned a value from the system sequence factory as the class does not declare a specific one.

<jdo>
  <package name="com.xyz">
    <class name="Company" objectid-class="CompanyId">
      <field name="id" primary-key="true">
        <extension vendor-name="kodo" key="sequence-assigned" value="true"?>
      </field>
    </class>
  </package>
</jdo>