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

JavaHibernateJpaUniqueidentifierId Generation

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

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

Solution 3 - Java


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

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. [1]: http://blog.eyallupu.com/2011/01/hibernatejpa-identity-generators.html

Solution 4 - Java

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1317764View Question on Stackoverflow
Solution 1 - JavaManuPKView Answer on Stackoverflow
Solution 2 - JavaVlad MihalceaView Answer on Stackoverflow
Solution 3 - JavaEyal LupuView Answer on Stackoverflow
Solution 4 - JavaAdelinView Answer on Stackoverflow