9.7. Generators
Prev | Chapter 9. Runtime Extensions | Next

## 9.7. Generators

The JPA Overview's Chapter 12, Mapping Metadata details using generators to automatically populate identity fields in JPA.

The JDO Overview demonstrates how to declare sequences in Chapter 15, Mapping Metadata. It describes JDO's `javax.jdo.Sequence` interface and how to obtain named sequences in JDO in Chapter 16, Sequence.

Kodo represents all generators internally with the `kodo.kernel.Seq` interface. This interface supplies all the context you need to create your own custom generators, including the current persistence environment, the JDBC `DataSource`, and other essentials. The `kodo.jdbc.kernel.AbstractJDBCSeq` helps you create custom JDBC-based sequences. Kodo also supplies the following built-in `Seq`s:

- `table`: This is Kodo's default implementation. It is an alias for the `kodo.jdbc.kernel.TableJDBCSeq` class. The `TableJDBCSeq` uses a special single-row table to store a global sequence number. If the table does not already exist, it is created the first time you run the mapping tool's on a class that requires it. You can also use the class' `main` method or the `sequencetable` shell/bat script to manipulate the table; see the `TableJDBCSeq.main` method Javadoc for usage details.

  This `Seq` has the following properties:

  - `Table`: The name of the sequence number table to use. Defaults to `KODO_SEQUENCE_TABLE`.

  - `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`.

  - `Allocate`: The number of values to allocate on each database trip. Defaults to 50, meaning the class 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 sequence number requests.

- `class-table`: This is an alias for the `kodo.jdbc.kernel.ClassTableJDBCSeq` . This `Seq` is like the `TableJDBCSeq` above, but maintains a separate table row, and therefore a separate sequence number, for each base persistent class. It has all the properties of the `TableJDBCSeq`. Its table name defaults to `KODO_SEQUENCES_TABLE`. It also adds the following properties:

  - `IgnoreUnmapped`: Whether to ignore unmapped base classes, and instead use one row per least-derived mapped class. Defaults to `false`.

  - `UseAliases`: Whether to use each class' entity name as the primary key value of each row, rather than the full class name. Defaults to `false`.

  As with the `TableJDBCSeq`, the `ClassTableJDBCSeq` creates its table automatically during mapping tool runs. However, you can manually manipulate the table through the class' `main` method, or through the `classsequencetable` shell/bat script. See the Javadoc for the `ClassTableJDBCSeq.main` method for usage details.

- `value-table`: This is an alias for the `kodo.jdbc.kernel.ValueTableJDBCSeq` . This `Seq` is like the `ClassTableJDBCSeq` above, but has an arbitrary number of rows for sequence values, rather than a fixed pattern of one row per class. Its table defaults to `KODO_SEQUENCES_TABLE`. It has all the properties of the `TableJDBCSeq`, plus:

  - `PrimaryKeyValue`: The primary key value used by this instance.

  As with the `TableJDBCSeq`, the `ValueTableJDBCSeq` creates its table automatically during mapping tool runs. However, you can manually manipulate the table through the class' `main` method, or through the `valuesequencetable` shell/bat script. See the Javadoc for the `ValueTableJDBCSeq.main` method for usage details.

- `native`: This is an alias for the `kodo.jdbc.kernel.NativeJDBCSeq`. Many databases have a concept of "native sequences" - a built-in mechanism for obtaining incrementing numbers. For example, in Oracle, you can create a database sequence 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 provides support for this common mechanism of sequence generation with the `NativeJDBCSeq`, which accepts the following properties:

  - `Sequence`: The name of the database sequence. Defaults to `KODO_SEQUENCE`.

  - `InitialValue`: The initial sequence value. Defaults to 1.

  - `Increment`: The amount the sequence increments. Defaults to 1.

  - `Allocate`: Some database can allocate values in-memory to service subsequent sequence requests faster.

- `time`: This is an alias for the `kodo.kernel.TimeSeededSeq`. This type uses an in-memory static counter, initialized to the current time in milliseconds and monotonically incremented for each value requested. It is only suitable for single-JVM environments.

You can use JPA `SequenceGenerator`s to describe any built-in `Seq`s or your own `Seq` implementation. Set the `sequenceName` attribute to a plugin string describing your choice. See Section 12.5, “Generators” in the JPA Overview for details on defining `SequenceGenerator`s.

You can create named JDO sequences using any of the built-in `Seq`s or your own `Seq` implementation. Just set the `sequence` element's `factory-class` attribute to a plugin string describing your choice. See Section 15.3, “Sequences” in the JDO Overview for details on defining named sequences in mapping metadata.

See Section 2.5, “Plugin Configuration” for plugin string formatting.

Example 9.16. Named Seq Sequence

JPA:

    @Entity
    @Table(name="AUTO")
    public class Author
    {
        @Id
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="AuthorSeq")
        @SequenceGenerator(name="AuthorSeq" sequence="table(Table=AUTO_SEQ, Increment=100)")
        @Column(name="AID")
        private long id;

        ...
    }

Note that if you want to use a plugin string without any arguments, you must still suffix the plugin type with `()` to differentiate it from a sequence name in the `SequenceGenerator.sequence` attribute:

    @SequenceGenerator(name="AuthorSeq", sequence="table()")

JDO:

    <?xml version="1.0"?>
    <orm>
        <package name="org.mag.pub">
            <sequence name="AuthorSeq" factory-class="table(Table=AUTH_SEQ, Increment=100)"/>
            <class name="Author" table="AUTH">
                <datastore-identity sequence="AuthorSeq" column="AID"/>
                ...
            </class>
        </package>
    </orm>

Kodo maintains a system sequence to generate datastore identity values for classes that do not declare a specific datastore identity strategy. You can configure the system sequence through the `kodo.Sequence` configuration property. This property accepts a plugin string describing a `Seq` instance.

Example 9.17. System Sequence Configuration

JPA XML format:

    <property name="kodo.Sequence" value="table(Table=KODOSEQ, Increment=100)"/>

JDO properties format:

    kodo.Sequence: table(Table=KODOSEQ, Increment=100)

In JPA, set your `GeneratedValue` annotation's `strategy` attribute to `AUTO` to use the configured system sequence. Or, because `AUTO` is the default strategy, use the annotation without attributes:

    @GeneratedValue
    private long id;

In JDO, set the `sequence` attribute of your `datastore-identity` or `field` element to `system` to use the system sequence:

    <field name="id" primary-key="true" sequence="system"/>

### 9.7.1. Runtime Access

Kodo JPA allows you to access named generators at runtime through the `OpenJPAEntityManager.getNamedGenerator` method:

    public Generator getNamedGenerator (String name);

The returned `org.apache.openjpa.persistence.Generator` is a facade over an internal Kodo `Seq`.

The `OpenJPAEntityManager` includes additional APIs to retrieve the identity generator of any class, or the generator of any field. With these APIs, you do not have to know the generator name. Additionally, they allow you to access the implicit generator used by default for datastore identity classes. See the Javadoc for the `OpenJPAEntityManager.getIdentityGenerator` and `OpenJPAEntityManager.getFieldGenerator` methods for API details.

The JDO Overview demonstrates how to obtain a sequence by name in Chapter 16, Sequence. The `KodoJDOHelper` includes additional APIs to retrieve the identity sequence of any class, or the value sequence of any field. With these APIs, you do not have to know the sequence name. Additionally, they allow you to access the implicit sequence used for a datastore identity class with the default `native` strategy, or the backing sequence of a field with a value strategy of `uuid-hex` or `uuid-string`.

See the Javadoc for the `KodoJDOHelper.getIdentitySequence` and `KodoJDOHelper.getFieldSequence` methods for API details. Note that all methods return instances of `javax.jdo.Sequence` to coincide with JDO's standard APIs; the `Seq` interface is only used internally.

Prev | Up | Next
9.6. Query Language Extensions | Home | 9.8. Transaction Events