5.  Generators

5.1. Sequence Generator
5.2. TableGenerator
5.3. Example

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

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

OpenJPA allows you to use one of OpenJPA'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 openjpa.Sequence configuration property. See the Reference Guide's Section 6, “ 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.

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

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>