12.5. Generators
Prev | Chapter 12. Mapping Metadata | Next

## 12.5. Generators

One aspect of identity mapping not covered in the previous section is EJB's ability to automatically assign a value to your numeric identity fields using generators. We discussed the available generator types in Section 5.2.2, “Id”. Now we show you how to define named generators.

### 12.5.1. Sequence Generator

Most databases allow you to create native sequences. These are database structures that generate increasing numeric values. The `SequenceGenerator` annotation represents a named database sequence. You can place the annotation on any package, entity class, persistent field declaration (if your entity uses field access), or getter method for a persistent property (if your entity uses property access). `SequenceGenerator` has the following properties:

- `String name`: The generator name. This property is required.

- `String sequenceName`: The name of the database sequence. If you do not specify the database sequence, your vendor will choose an appropriate default.

- `int initialValue`: The initial sequence value.

- `int allocationSize`: Some databases can pre-allocate groups of sequence values. This allows the database to service sequence requests from cache, rather than physically incrementing the sequence with every request. This allocation size defaults to 50.

| Note
Kodo allows you to use describe one of Kodo's built-in generator implementations in the `sequenceName` property. You can also set the `sequenceName` to `system` to use the system sequence defined by the `kodo.Sequence` configuration property. See the Reference Guide's Section 9.7, “Generators” for details.

The XML element for a sequence generator is `sequence-generator`. Its attributes mirror the above annotation's properties:

- `name`

- `sequence-name`

- `initial-value`

- `allocation-size`

To use a sequence generator, set your `GeneratedValue` annotation's `strategy` property to `GenerationType.SEQUENCE`, and its `generator` property to the sequence generator's declared name. Or equivalently, set your `generated-value` XML element's `strategy` attribute to `SEQUENCE` and its `generator` attribute to the generator name.

### 12.5.2. TableGenerator

A `TableGenerator` refers to a database table used to store increasing sequence values for one or more entities. As with `SequenceGenerator`, you can place the `TableGenerator` annotation on any package, entity class, persistent field declaration (if your entity uses field access), or getter method for a persistent property (if your entity uses property access). `TableGenerator` has the following properties:

- `String name`: The generator name. This property is required.

- `String table`: The name of the generator table. If left unspecified, your vendor will choose a default table.

- `String schema`: The named table's schema.

- `String catalog`: The named table's catalog.

- `String pkColumnName`: The name of the primary key column in the generator table. If unspecified, your implementation will choose a default.

- `String valueColumnName`: The name of the column that holds the sequence value. If unspecified, your implementation will choose a default.

- `String pkColumnValue`: The primary key column value of the row in the generator table holding this sequence value. You can use the same generator table for multiple logical sequences by supplying different `pkColumnValue`s. If you do not specify a value, the implementation will supply a default.

- `int initialValue`: The value of the generator's first issued number.

- `int allocationSize`: The number of values to allocate in memory for each trip to the database. Allocating values in memory allows the EJB persistence runtime to avoid accessing the database for every sequence request. This number also specifies the amount that the sequence value is incremented each time the generator table is updated. Defaults to 50.

The XML equivalent is the `table-generator` element. This element's attributes correspond exactly to the above annotation's properties:

- `name`

- `table`

- `schema`

- `catalog`

- `pk-column-name`

- `value-column-name`

- `pk-column-value`

- `initial-value`

- `allocation-size`

To use a table generator, set your `GeneratedValue` annotation's `strategy` property to `GenerationType.TABLE`, and its `generator` property to the table generator's declared name. Or equivalently, set your `generated-value` XML element's `strategy` attribute to `TABLE` and its `generator` attribute to the generator name.

### 12.5.3. Example

Let's take advantage of generators in our entity model. Here are our updated mappings.

Example 12.4. Generator Mapping

    package org.mag;

    @Entity
    @IdClass(Magazine.MagazineId.class)
    @Table(name="MAG")
    public class Magazine
    {
        @Column(length=9)
        @Id private String isbn;
        @Id private String title;

        ...

        public static class MagazineId
        {
            ...
        }
    }

    @Entity
    @Table(name="ART", uniqueConstraints=@Unique(columnNames="TITLE"))
    @SequenceGenerator(name="ArticleSeq", sequenceName="ART_SEQ")
    public class Article
    {
        @Id
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="ArticleSeq")
        private long id;

        ...
    }

    package org.mag.pub;

    @Entity
    @Table(name="COMP")
    public class Company
    {
        @Column(name="CID")
        @Id private long id;

        ...
    }

    @Entity
    @Table(name="AUTH")
    public class Author
    {
        @Id
        @GeneratedValue(strategy=GenerationType.TABLE, generator="AuthorGen")
        @TableGenerator(name="AuthorGen", table="AUTH_GEN", pkColumnName="PK",
            valueColumnName="AID")
        @Column(name="AID", columnDefinition="INTEGER64")
        private long id;

        ...
    }

    @Embeddable
    public class Address
    {
        ...
    }

    package org.mag.subscribe;

    @MappedSuperclass
    public abstract class Document
    {
        @Id
        @GeneratedValue(generate=GenerationType.IDENTITY)
        private long id;

        ...
    }

    @Entity
    @Table(schema="CNTRCT")
    public class Contract
        extends Document
    {
        ...
    }

    @Entity
    @Table(name="SUB", schema="CNTRCT")
    public class Subscription
    {
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        private long id;

        ...

        @Entity
        @Table(name="LINE_ITEM", schema="CNTRCT")
        public static class LineItem
            extends Contract
        {
            ...
        }
    }

    @Entity(name="Lifetime")
    public class LifetimeSubscription
        extends Subscription
    {
        ...
    }

    @Entity(name="Trial")
    public class TrialSubscription
        extends Subscription
    {
        ...
    }

The same metadata for `Article` and `Author` expressed in XML form:

    <entity class="org.mag.Article">
        <table name="ART">
            <unique-constraint>
                <column-name>TITLE</column-name>
            </unique-constraint>
        </table>
        <sequence-generator name="ArticleSeq" sequence-name="ART_SEQ"/>
        <attributes>
            <id name="id">
                <generated-value strategy="SEQUENCE" generator="ArticleSeq"/>
            </id>
            ...
        </attributes>
    </entity>
    <entity class="org.mag.pub.Author">
        <table name="AUTH"/>
        <attributes>
            <id name="id">
                <column name="AID" column-definition="INTEGER64"/>
                <generated-value strategy="TABLE" generator="AuthorGen"/>
                <table-generator name="AuthorGen" table="AUTH_GEN"
                    pk-column-name="PK" value-column-name="AID"/>
            </id>
            ...
        </attributes>
    </entity>

Prev | Up | Next
12.4. Identity Mapping | Home | 12.6. Inheritance