Hibernate Tip: How does Hibernate’s native ID generator work

By Thorben Janssen

Association Mapping, Best Practice, Mapping, Primary Key

Hibernate Tips is a series of posts in which I describe a quick and easy solution for common Hibernate questions. If you have a question for a future Hibernate Tip, please post a comment below.

Question:

One of the readers of my article about using Hibernate with a MySQL database asked the following question:

What is the difference between the following two recommended approaches concerning the primary keys?

@GeneratedValue(strategy = GenerationType.IDENTITY)
@GeneratedValue(generator = "native")
@GenericGenerator(name = "native", strategy = "native")

Solution:

As so often in software development, the answer to that question is: “It depends …”. In this case, it depends on the Dialect that you configured in your persistence.xml.

The native strategy

When you use a @GenericGenerator that references the native strategy, Hibernate uses the strategy natively supported by the configured Dialect. You can find the corresponding code in the of the Dialect class. Here’s is the code that’s used in Hibernate 5.4.

public String getNativeIdentifierGeneratorStrategy() {
	if ( getIdentityColumnSupport().supportsIdentityColumns() ) {
		return "identity";
	}
	else {
		return "sequence";
	}
}

For all commonly used databases, except MySQL, this method returns the String “sequence”. If you’re using a MySQL dialect, it returns “identity”.

Using the native strategy with different dialects

Let’s use the following, simple entity with a MySQL and a PostgreSQL database.

@Entity
public class Author {

	@Id
	@GeneratedValue(generator = "native")
	@GenericGenerator(name = "native", strategy = "native")
	private Long id;
	
	@Version
	private int version;

	private String firstName;

	private String lastName;
	
	...

}

When you persist a new Author entity using the PostgreSQL dialect, you can see that Hibernate uses the sequence native to generate the primary key value. And in the next step, it inserts the new record.

14:03:27,709 DEBUG [org.hibernate.SQL] - 
    select
        nextval ('native')
14:03:27,742 INFO  [org.thoughts.on.java.model.TestIdentityStrategy] - After persist
14:03:27,758 DEBUG [org.hibernate.SQL] - 
    insert 
    into
        Author
        (firstName, lastName, version, id) 
    values
        (?, ?, ?, ?)

If you use a MySQL database instead, you can see that Hibernate utilizes an auto-incremented column instead.

14:05:15,739 DEBUG [org.hibernate.SQL] - 
    insert 
    into
        Author
        (firstName, lastName, version) 
    values
        (?, ?, ?)
14:05:15,760 DEBUG [org.hibernate.id.IdentifierGeneratorHelper] - Natively generated identity: 1

The differences between native and identity strategy

So, as long as you use both mappings with a MySQL database, the result will be the same. But there are still a few differences:

  1. The behavior of the native strategy changes if your database dialect returns a different strategy as the natively supported one. That could happen because you now use a different database dialect or the internal implementation of the dialect changed.
  2. The @GenericGenerator mapping is much harder to read because it depends on the implementation of your database dialect.
  3. The @GenericGenerator annotation is Hibernate-specific. So, you can’t use this mapping with any other JPA implementation.

Mapping Recommendations

If you’ve read some of my other tutorials, you can probably guess my preferred mapping. I strongly recommend using the IDENTITY mapping instead of the native one. There are multiple reasons for that. The most obvious ones are the better readability and better portability to other JPA implementations.

But you also need to keep in mind that the generation of primary keys can have a significant impact on the performance of your application. I, therefore, want to define the strategy explicitly and don’t rely on any internal implementations.

I don’t see the adaptability of the native strategy to different database dialects as a huge advantage. For almost all dialects, Hibernate uses the SEQUENCE strategy anyways. And if you need to support MySQL databases, you can easily override the primary key strategy in your mapping file.

Learn more:

If you are interested in primary key mappings, you should also read the following articles:

 

Hibernate Tips Book







Get more recipes like this one in my new book Hibernate Tips: More than 70 solutions to common Hibernate problems.

It gives you more than 70 ready-to-use recipes for topics like basic and advanced mappings, logging, Java 8 support, caching, and statically and dynamically defined queries.

Get it now!



Tags

Association Mapping, Best Practice, Mapping, Primary Key


About the author

Thorben is an independent consultant, international speaker, and trainer specialized in solving Java persistence problems with JPA and Hibernate.
He is also the author of Amazon’s bestselling book Hibernate Tips - More than 70 solutions to common Hibernate problems.

Books and Courses

Coaching and Consulting

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}