In JPA terms, the @Id annotation indicates the identifier of the entity maps the primary key of a Database Table. In this article we will learn how to choose the optimal strategy for primary key generation.
JPA applications can use the @Id Column in combination with a @GeneratedValue annotation to choose the strategy for primary key generation.
You can choose among four different id generation strategies by specifying a strategy in the strategy element. The value can be any one of AUTO, TABLE, SEQUENCE, or IDENTITY enumerated values of the GenerationType enumerated type.
Let’s go in detail with each option.
GenerationType.AUTO
If you want to delegate the choice of the strategy to the Database, you can specify a strategy of AUTO. Example:
@Entity public class Employee { @Id @GeneratedValue(strategy=GenerationType.AUTO) private Long id; // … }
Pro Tip
GenerationType.AUTO is the default strategy therefore it is sufficient to annotate your @Id with @GeneratedValue. This strategy lets the JPA implementation to choose the best strategy based on the database dialect. For most of the common databases, it picks GenerationType.SEQUENCE.
Be careful! Failure to provide the correct database dialect may cause errors when you generate the primary key.
GenerationType.TABLE
This is the most flexible approach even though not the best performance option. You can use it for databases which do not have sequences so that id are stored in a separate table governed by pessimistic locks.
The easiest way to use a table to generate identifiers is to simply specify the generation strategy to be TABLE in the strategy element:
@Id @GeneratedValue(strategy=GenerationType.TABLE) private int id;
A more explicit approach would be to actually specify the table for id storage. We can define one by using a @TableGenerator annotation and then refer to it by name in the @GeneratedValue annotation:
@TableGenerator(name="Emp_Gen") @Id @GeneratedValue(generator="Emp_Gen") private int id;
As said, this strategy provides the worst performance and should be avoided if possible.
GenerationType.SEQUENCE
Many databases support Sequences as an internal mechanism for id generation. If we are not concerned that it be any particular sequence, specifying the generator type alone should be sufficient:
@Id @GeneratedValue(strategy=GenerationType.SEQUENCE) private int id;
In this case, the provider will use a default sequence object of its own choosing. The other option would be to define a sequence generator name and refer to it in the @GeneratedValue annotation:
@SequenceGenerator(name="Emp_Gen", sequenceName="Emp_Seq") @Id @GeneratedValue(generator="Emp_Gen") private int getId;
More in detail, in the above snippet we have:
- The generator attribute of the @GeneratedValue annotation references the name attribute of the @SequenceGenerator annotation.
- The sequenceName attribute of the @SequenceGenerator rerefences the database sequence object
- Finally, the allocationSize instructs the JPA provider with the number of values that can be allocated by the application using a single database sequence call.
The JPA provider will create the sequence for you if you allow schema generation. If that is not the case, you need to add to the DDL the SQL for your sequence. Example:
CREATE SEQUENCE Emp_Seq MINVALUE 1 START WITH 1 INCREMENT BY 50
More details about Sequence Strategy in this article: How do you bind the Id of an Entity to a Sequence ?
GenerationType.IDENTITY
Identity is often used when the database does not support sequences or because there’s support for auto-increment database columns. For example, MYSQL supports auto-increment field therefore this strategy is optimal for this database vendors.
For others DB it is generally less efficient because you cannot allocate them in blocks and because the identifier is not available until after commit time. To indicate that IDENTITY generation should occur, you should use the @GeneratedValue annotation with strategy of IDENTITY.
Example:
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id;
Which is the best Strategy for Primary Key Generation ?
We can summarize the above options in the following key points:
- If your Database supports Sequences, then choose the GenerationType.SEQUENCE as strategy
- On the other hand, if your Database supports auto-increment fields (e.g. MySQL), then choose GenerationType.IDENTITY as strategy
- Finally, if you are not sure which id generation strategy to use, just use GenerationType.AUTO and delegate the choice to the DB.