Primary Key Generation Strategies in Hibernate
In this post we will explore useful Key Generation Strategies in Hibernate for MYSQL DB.
Each database table row usually will be identified by a unique column value. Using this value one can fetch data and identify the data. This key plays important role in managing the relational data. This unique identity can be called key or id.
Some tables might not have a single id but can have unique combinations of column values together. In many tables the sole purpose of id will be to identify row. The data is not changed once it is created. The id should be unique. So the key generation strategies come into picture. Some databases provide support for identity columns (like auto_increment sequence in mysql) which will return unique identity during insert in integer or long. Some other databases provide facility of sequences where one can define sequences to produce new id and then insert it into the table etc.
When using ORM like Hibernate, the ORM should provide ways to generate key or to use the underlying db key generation implementation without much hassle. It should delegate the burden of creating id values from developers.
JPA also defines some techniques some of which present in Hibernate also.
One can specify the key generation techniques in hibernate’s XML mapping file like below:
<id name=”task_id” type=”int” column=”user_task_id” node=”id”>
<generator name=”generator_name”/>
</id>
If you want to do it in annotations you can do it as following:
Define the generic generator name at top of the class:
@org.hibernate.annotations.GenericGenerator(
name = “test-native-strategy”,
strategy = “native”)
Where strategy is one among the strategies explained below and name is the strategy name. (Which we use when defining id)
On either getter method or the field declaration we must have:
@Id
@GeneratedValue(generator = “test-native-strategy”)
@Column(name=”user_task_id “)
The name in the
@org.hibernate.annotations.GenericGenerator
And Generator in the
@GeneratedValue(generator = “test-native-strategy”)
Values should match.
Some of the Key Generation techniques in Hibernate are:
1. Native: This generation strategy is the default. It simply chooses the primary key generation strategy that is the default for the database in question, which quite typically is IDENTITY, although it might be TABLE or SEQUENCE depending upon how the database is configured. The native strategy is typically recommended, as it makes your code and your applications most portable.
For example:
In Mysql if you have primary key column as a auto_increment, the db will be updated using this strategy
2. identity:. This generates a Integer, long or short type of ids. Identity column generator is supported by mysql,db2, MSSQL etc. This allows database to generate a unique key. How the db implements is dependent upon the Db.
You can test in mysql by defining the primary key column auto_increment. Both native and identity effects looks same here.
3. Sequence: This generates an Integer, long or short type of ids. This strategy is supported in db2, Oracle, PostgreSQL etc. Not in Mysql. To use it, one has to create a sequence in database, and should define the sequence name, its DB name, initial value etc in a<sequence-generator>
This is not covered here
4. Increment: This generates a Integer, long or short type of ids. This strategy or similar strategy is not defined in JPA. This generator reads maximum present primary key in database table and then increments it by one and inserts new row with new id.
Eg: XML mapping way:
Define generator class as ‘increment’ in id tag:
<id name=”task_id” type=”int” column=”user_task_id” node=”id”>
<generator name=”increment”/>
</id>
using annotations:
Define the generic generator name at top of the class:
@org.hibernate.annotations.GenericGenerator(
name = “test-increment-strategy”,
strategy = “increment”)
Where strategy is one of the strategies explained below and name is the strategy name. (Which we use when defining id)
on either getter method or the field declaration we must have:
@Id
@GeneratedValue(generator = ” test-increment-strategy”)
@Column(name=”user_task_id “)
The reading of maximum id value happens only once during Hibernate startup. (using query: select max(id_col_name) from table_name)
So there is a risk involved with this approach. If there is any other application inserts data into the table, then the hibernate can overwrite the db row. So when using this technique one has to be sure that hibernate application is the single one accessing the db and no one inserts into table.
5. hilo: This generates a Integer, long or short type of ids. This uses a High – Low algorithm. As the name suggests, it depends upon the highest table id and then reads the possible lowest available value.
To use it one should have a table by name hibernate_unique_key in the database. One like below:
create table hibernate_unique_key(
next_hi int(11));
insert initial value into it.
insert into hibernate_unique_key values(1);
Now to use this strategy, define your id tag’s generator in configuration file as below:
<id name=”task_id” type=”int” column=”user_task_id” node=”id”>
<generator name=”hilo”> </generator>
</id>
If you want to do in annotations then:
Define the generic generator name at top of the class:
@org.hibernate.annotations.GenericGenerator(
name = “test-hilo-strategy”,
strategy = “hilo”)
where strategy is one of the strategies explained below and name is the strategy name.(which we use when defining id)
on either getter method or the field declaration we must have:
@Id
@GeneratedValue(generator = ” test-hilo-strategy”)
@Column(name=”user_task_id “)
(You can use different table name other than hibernate_unique_key and different column name other than next_hi. If so you have to specify them in the <id>’s <generator tag as below:
<generator>
<param name=”table”>hibernate_unique_key</param>
<param name=”column”>next</param>
<param name=”max_lo”>1</param>
</generator>
)
Now when you insert data, then you can see the value of next column of table hibernate_unique_key being incremented by 1.
It generates new id as follows:
This algorithm generates key which are unique only for a particular database. High values are retrieved from global source and made unique by adding local low values.
6. seqhilo: This is similar to hilo , but it uses the database sequence to generate id. This can’t be used in MYSQL.
7. uuid.hex: This generates String type of ids. So your table id should be a string. This method uses IP address with timestamp to generate unique String identifier. This id will be unique across multiple databases. So this can be used if you are using 2 databases in same app or you merge 2 databases.
Eg: XML mapping way:
Define generator class as ‘uuid.hex in id tag:
<id name=”task_id” type=”int” column=”user_task_id” node=”id”>
<generator name=”uuid.hex”/>
</id>
using annotations:
Define the generic generateor name at top of the class:
@org.hibernate.annotations.GenericGenerator(
name = “test-uuid-strategy”,
strategy = “uuid.hex”)
Where strategy is one of the strategies explained below and name is the strategy name.(which we use when defining id)
on either getter method or the field declaration we must have:
@Id
@GeneratedValue(generator = ” test- uuid -strategy”)
@Column(name=”user_task_id “)
8. guid: This Also generates String type of ids. This strategy generates ids using database-generated globally unique identifier String. This can be used in MYSQL and SQL servers.
In MYSQL it fires following query to find out unique identifier string :
select uuid() which Return a Universal Unique Identifier (UUID).
It can be used similar to uuid.hex. Just replace the <generator class by “guid”.








