[java] How to choose the id generation strategy when using JPA and Hibernate

I was going through Id generation section of the Hibernate reference guide and "java persistence with Hibernate"

There are quite a few options available with Hibernate and JPA combined.

I was looking for a further documentation on how to choose the specific id generation strategy.

I am also looking for tipping points.

For example, hilo strategy is expected to reduce contention. I am assuming there must be a trade off associated with this choice.

I want to be educated about the trade offs.

Is there any literature available?

This question is related to java hibernate jpa uniqueidentifier id-generation

The answer is


I find this lecture very valuable https://vimeo.com/190275665, in point 3 it summarizes these generators and also gives some performance analysis and guideline one when you use each one.


The API Doc are very clear on this.

All generators implement the interface org.hibernate.id.IdentifierGenerator. This is a very simple interface. Some applications can choose to provide their own specialized implementations, however, Hibernate provides a range of built-in implementations. The shortcut names for the built-in generators are as follows:

increment

generates identifiers of type long, short or int that are unique only when no other process is inserting data into the same table. Do not use in a cluster.

identity

supports identity columns in DB2, MySQL, MS SQL Server, Sybase and HypersonicSQL. The returned identifier is of type long, short or int.

sequence

uses a sequence in DB2, PostgreSQL, Oracle, SAP DB, McKoi or a generator in Interbase. The returned identifier is of type long, short or int

hilo

uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int, given a table and column (by default hibernate_unique_key and next_hi respectively) as a source of hi values. The hi/lo algorithm generates identifiers that are unique only for a particular database.

seqhilo

uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int, given a named database sequence.

uuid

uses a 128-bit UUID algorithm to generate identifiers of type string that are unique within a network (the IP address is used). The UUID is encoded as a string of 32 hexadecimal digits in length.

guid

uses a database-generated GUID string on MS SQL Server and MySQL.

native

selects identity, sequence or hilo depending upon the capabilities of the underlying database.

assigned

lets the application assign an identifier to the object before save() is called. This is the default strategy if no element is specified.

select

retrieves a primary key, assigned by a database trigger, by selecting the row by some unique key and retrieving the primary key value.

foreign

uses the identifier of another associated object. It is usually used in conjunction with a primary key association.

sequence-identity

a specialized sequence generation strategy that utilizes a database sequence for the actual value generation, but combines this with JDBC3 getGeneratedKeys to return the generated identifier value as part of the insert statement execution. This strategy is only supported on Oracle 10g drivers targeted for JDK 1.4. Comments on these insert statements are disabled due to a bug in the Oracle drivers.

If you are building a simple application with not much concurrent users, you can go for increment, identity, hilo etc.. These are simple to configure and did not need much coding inside the db.

You should choose sequence or guid depending on your database. These are safe and better because the id generation will happen inside the database.

Update: Recently we had an an issue with idendity where primitive type (int) this was fixed by using warapper type (Integer) instead.



A while ago i wrote a detailed article about Hibernate key generators: http://blog.eyallupu.com/2011/01/hibernatejpa-identity-generators.html

Choosing the correct generator is a complicated task but it is important to try and get it right as soon as possible - a late migration might be a nightmare.

A little off topic but a good chance to raise a point usually overlooked which is sharing keys between applications (via API). Personally I always prefer surrogate keys and if I need to communicate my objects with other systems I don't expose my key (even though it is a surrogate one) – I use an additional ‘external key’. As a consultant I have seen more than once 'great' system integrations using object keys (the 'it is there let's just use it' approach) just to find a year or two later that one side has issues with the key range or something of the kind requiring a deep migration on the system exposing its internal keys. Exposing your key means exposing a fundamental aspect of your code to external constrains shouldn’t really be exposed to.


Basically, you have two major choices:

  • You can generate the identifier yourself, in which case you can use an assigned identifier.
  • You can use the @GeneratedValue annotation and Hibernate will assign the identifier for you.

For the generated identifiers you have two options:

  • UUID identifiers.
  • Numerical identifiers.

For numerical identifiers you have three options:

  • IDENTITY
  • SEQUENCE
  • TABLE

IDENTITY is only a good choice when you cannot use SEQUENCE (e.g. MySQL) because it disables JDBC batch updates.

SEQUENCE is the preferred option, especially when used with an identifier optimizer like pooled or pooled-lo.

TABLE is to be avoided since it uses a separate transaction to fetch the identifier and row-level locks which scales poorly.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to hibernate

Hibernate Error executing DDL via JDBC Statement How does spring.jpa.hibernate.ddl-auto property exactly work in Spring? Error creating bean with name 'entityManagerFactory' defined in class path resource : Invocation of init method failed JPA Hibernate Persistence exception [PersistenceUnit: default] Unable to build Hibernate SessionFactory Disable all Database related auto configuration in Spring Boot Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] HikariCP - connection is not available Hibernate-sequence doesn't exist How to find distinct rows with field in list using JPA and Spring? Spring Data JPA and Exists query

Examples related to jpa

No converter found capable of converting from type to type How does spring.jpa.hibernate.ddl-auto property exactly work in Spring? Deserialize Java 8 LocalDateTime with JacksonMapper Error creating bean with name 'entityManagerFactory' defined in class path resource : Invocation of init method failed How to beautifully update a JPA entity in Spring Data? JPA Hibernate Persistence exception [PersistenceUnit: default] Unable to build Hibernate SessionFactory How to return a custom object from a Spring Data JPA GROUP BY query How to find distinct rows with field in list using JPA and Spring? What is this spring.jpa.open-in-view=true property in Spring Boot? Spring Data JPA and Exists query

Examples related to uniqueidentifier

How to get a unique device ID in Swift? How to generate and manually insert a uniqueidentifier in sql server? Generate a unique id How to choose the id generation strategy when using JPA and Hibernate Convert NULL to empty string - Conversion failed when converting from a character string to uniqueidentifier .NET Short Unique Identifier Auto increment in MongoDB to store sequence of Unique User ID Is Secure.ANDROID_ID unique for each device? Hash function that produces short hashes? How to delete from select in MySQL?

Examples related to id-generation

How to choose the id generation strategy when using JPA and Hibernate