daniele levis pelusi 385076 unsplash - HIBERNATE ID GENERATION STRATEGIES

HIBERNATE ID GENERATION STRATEGIES

It was a regular day in the office. A consumer of our API started just migrated half of their load to our endpoints. Suddenly we get calls of locking insert statements on the underlying database. Here is wat we learned the hard way: Never use hibernate generation type TABLE in enterprise applications.

In small applications the differences are not that clear. But here are the candidates:

 

Generation type AUTO and IDENTITY

These types delegate the control of the id generation. Generation type AUTO chooses a strategy on the capabilities of the underlying relational database. Where generation type IDENTITY uses the auto-increment methods of the database (IDENTITY for SQL Server and AUTO_INCREMENT for MySQL).

 

Generation type TABLE

This was the generation type we found on our entity.

@Entity
@Table(name = "plant")
public class Plant {
 
    @Id
    @GeneratedValue(strategy=GenerationType.TABLE)
    private Long id;
    
    private String name;
    
    ...
}   

The problem is that every insert statement results in the following database actions:

  1. A lock is put on the hibernate-sequences table
  2. The value is incremented
  3. The new value is saved (releasing the row-level lock)

This strategy has a performance overhead as you can see directly. But it performs dramatically if multiple threads are involved as shown in this post by Vlad Mihalcea.

 

Generation type SEQUENCE

This generation type uses a sequence, a separate database entity specialised in this task. The multiple steps we saw with the previous generation type can be done in a single one with this strategy. More importantly there is no locking involved and therefore scales a lot better in a enterprise setting. Here is an example of how this is done.

@Entity
@Table(name = "plant")
public class Plant {
 
    @Id
    @GeneratedValue(
        generator = "sequence", 
        strategy = GenerationType.SEQUENCE
    )
    @SequenceGenerator(
        name = "sequence", 
        allocationSize = 10
    )
    private Long id;
 
    private String name;
 
    ...
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *