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

## 6. Generators

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

OpenJPA represents all generators internally with the `org.apache.openjpa.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 `org.apache.openjpa.jdbc.kernel.AbstractJDBCSeq` helps you create custom JDBC-based sequences. OpenJPA also supplies the following built-in `Seq`s:

- `table`: This is OpenJPA's default implementation. It is an alias for the `org.apache.openjpa.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 on a class that requires it. You can also use the class's `main` method 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 `OPENJPA_SEQUENCE_TABLE`. If the entities are mapped to the same table name but with different schema name within one PersistenceUnit, one `OPENJPA_SEQUENCE_TABLE` is created for each schema.

  - `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 `org.apache.openjpa.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 `OPENJPA_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. See the Javadoc for the `ClassTableJDBCSeq.main` method for usage details.

- `value-table`: This is an alias for the `org.apache.openjpa.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 `OPENJPA_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. See the Javadoc for the `ValueTableJDBCSeq.main` method for usage details.

- `native`: This is an alias for the `org.apache.openjpa.jdbc.kernel.NativeJDBCSeq`. Many databases have a concept of "native sequences" - a built-in mechanism for obtaining incrementing numbers. For example, in Oracle database, 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`. OpenJPA 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 `OPENJPA_SEQUENCE`.

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

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

  - `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, which in turn means it only has to make a database trip to get new sequence numbers once every 50 sequence number requests.

- `time`: This is an alias for the `org.apache.openjpa.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.

> If specifying your own class name, you must include parentheses at the end of the class name, even if you have no plugin properties to configure. (E.g., `sequenceName="com.example.SeqImpl()"`.

See Section 5, “ Generators ” in the JPA Overview for details on defining `SequenceGenerator`s.

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

Example 9.8. Named Seq Sequence

    @Entity
    @Table(name="AUTO")
    public class Author {

        @Id
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="AuthorSeq")
        @SequenceGenerator(name="AuthorSeq", sequenceName="table(Table=AUTO_SEQ)", allocationSize=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.sequenceName` attribute:

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

OpenJPA 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 `openjpa.Sequence` configuration property. This property accepts a plugin string describing a `Seq` instance.

Example 9.9. System Sequence Configuration

    <property name="openjpa.Sequence" value="time(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;

### 6.1. Runtime Access

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

Prev | Up | Next
5. MethodQL | Home | 7. Transaction Events