The JPA Overview's Chapter 12, 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, 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" 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()")
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="table(Table=OPENJPASEQ, 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;
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.