Why should not use the AUTO JPA GenerationType with MySQL and Hibernate

Introduction

As I already mentioned, you should never use the TABLE identifier generator since it does not scale properly. In this post, I’ll show you why you should not rely on the AUTO GenerationType strategy if you’re Hibernate application uses MySQL.

Prior to Hibernate 5

On Hibernate 4, if you had the following entity mapping:

@Entity(name = "Post")
@Table(name = "post")
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String title;

    public Post() {}

    public Post(String title) {
        this.title = title;
    }
}

When persisting 3 Post entities:

for ( int i = 1; i <= 3; i++ ) {
    entityManager.persist( 
        new Post( 
            String.format( 
                "High-Performance Java Persistence, Part %d", i
            ) 
        ) 
    );
}

Hibernate would generate the following insert statements:

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 1')

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 2')

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 3')

That’s great! Hibernate used the IDENTITY column to generate the entity identifier which is the only reasonable option for MySQL.

Hibernate 5

If you run the same unit test on Hibernate 5, you’ll get the following SQL statements:

SELECT next_val as id_val 
FROM hibernate_sequence FOR UPDATE

UPDATE hibernate_sequence 
SET next_val= 2 where next_val=1

SELECT next_val as id_val 
FROM hibernate_sequence FOR UPDATE

UPDATE hibernate_sequence 
SET next_val= 3 where next_val=1

SELECT next_val as id_val 
FROM hibernate_sequence FOR UPDATE

UPDATE hibernate_sequence 
SET next_val= 4 where next_val=3

INSERT INTO post (title, id) 
VALUES ('High-Performance Java Persistence, Part 1', 1)

INSERT INTO post (title, id) 
VALUES ('High-Performance Java Persistence, Part 2', 2)

INSERT INTO post (title, id) 
VALUES ('High-Performance Java Persistence, Part 3', 3)

What’s just happened? Well, Hibernate picks the TABLE generator instead of IDENTITY when the underlying database does not support sequences. However, TABLE generator is not a good choice. Check out the HHH-11014 Jira issue for more details related to this behavior change.

How to fix it?

The fix is extremely easy. You just need to use the native identifier instead:

@Id
@GeneratedValue(
    strategy= GenerationType.AUTO, 
    generator="native"
)
@GenericGenerator(
    name = "native", 
    strategy = "native"
)
private Long id;

Now, when running the previous test case, Hibernate uses the IDENTITY column instead:

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 1')

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 2')

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 3')

If you want to use a portable solution that manages to customize the SEQUENCE generator while still allowing you to pick the IDENTITY generator for MySQL, then check out this article.

If you enjoyed this article, I bet you are going to love my book as well.

Conclusion

JPA portability is a myth! In reality, you have to know the details of the underlying JPA provider if you want a high-performance enterprise application.

If you liked this article, you might want to subscribe to my newsletter too.

Advertisements

8 thoughts on “Why should not use the AUTO JPA GenerationType with MySQL and Hibernate

  1. Hi Vlad, with that config its possible batching data in that way with MySQL? (sorry if i talk something wrong, not english speaker here 🙂

  2. Does this also apply to SQL Server and SQLServerDialect 2008? Today i migrated and app from SQLServerDialect to SQLServer2008Dialect and noticed this hibernate_sequence table. I;m also having issues with inserting rows after the migration and i wonder how my issues relate to this article.And again is this solution portable between MySQL and SQL Server?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s