How to generate UUIDs as primary keys with Hibernate

By Thorben Janssen

Mapping, Primary Key

Most developers prefer numerical primary keys because they are efficient to use and easy to generate. But that doesn’t mean that a primary key has to be a number.

UUIDs, for example, have gained some popularity over the recent years. The main advantage of a UUID is its (practical) global uniqueness which provides a huge advantage for distributed systems.

If you use the typical, numerical ID that gets incremented for each new record, you need to generate all IDs by the same component of your system or the components need to communicate with each other. With a globally unique UUID, you don’t need all of this. Each component can generate a UUID and there will not be any conflicts.

On the other hand, the UUID also has some disadvantages. The most obvious one is its size. It’s 4 times larger than a numerical ID and can’t be handled as efficiently. You should, therefore, decide carefully if you want to use UUIDs or numeric IDs and discuss it with your database administrator.

If you decide to use UUIDs, you can, of course, also persist them with Hibernate. With just a few additional annotations, you can even let Hibernate generate the UUIDs for you.

Generate UUIDs with Hibernate

The IETF RFC 4122 defines 4 different strategies to generate UUIDs. Hibernate’s UUIDGenerator supports 2 of them:

  1. The default strategy generates the UUID based on random numbers (IETF RFC 4122 Version 4).
  2. You can also configure a generator that uses the IP address of the machine and a timestamp (IETF RFC 4122 Version 1).

Let’s have a look at the default strategy first.

Random number based UUID (IETF RFC 4122 version 4)

By default, Hibernate uses a random number based generation strategy. As always, you don’t have to do much to get the default behaviour. You just need to add a @GeneratedValue annotation that references the ID generator to your primary key attribute and define the generator with one of Hibernate’s @GenericGenerator annotations. The @GenericGenerator annotation requires 2 parameters, the name of the generator and the name of the class that implements the generator. In this case, it’s the org.hibernate.id.UUIDGenerator.

That’s all you have to do to let Hibernate generate UUIDs as primary key values. You can see an example of it in the following code snippet.

When you now persist a new Book entity, Hibernate generates a UUID before writing the new record to the database.

IP and timestamp based UUID (IETF RFC 4122 version 1)

Hibernate can also generate a UUID based on IETF RFC 4122 version 1. If you follow the specification, you should generate the UUID with the MAC address instead of the IP address. As long as nobody is messing around with it, the MAC address of each device should be unique and due to this help to create a unique UUID.

Hibernate uses the IP address instead of the MAC address. In general, this is not an issue. But if the servers of your distributed system are running in different networks you should make sure that none of them share the same IP address.

The configuration of the IETF RFC 4122 version 1 based UUID generator is similar to the previous one but requires an additional parameter that defines the generation strategy. You can see an example of it in the following code snippet. You just need to provide an additional @Parameter annotation with the name uuid_gen_strategy_class and the fully qualified classname of the generation strategy as the value.

When you now persist the new Book entity, Hibernate will use the CustomVersionOneStrategy class to generate the UUID based on IETF RFC 4122 version 1.

Summary

As you’ve seen, you can also use UUIDs as primary keys and let Hibernate handle the value generation. Hibernate’s UUIDGenerator supports the creation of version 1 and version 4 UUIDs as defined by IETF RFC 4122. By default, it generates version 4 UUIDs which is a good fit for most use cases.

Unfortunately, this is not part of the JPA specification and will require some adaptions, if you need to switch your JPA implementation.


Tags

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 Repl​​​​​y

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.

    1. Sure. If you don’t annotate the UUID attribute with @Id, it’s treated as a normal entity attribute. You then need to generate and set the UUID yourself.

      Reply

    1. Hi Vinod,

      You can use primary keys of type UUID in the same way as any other primary keys.
      The easiest way to fetch a Book entity by its primary key would be: em.find(Book.class, myId);

      Regards,
      Thorben

      Reply

  1. Hi Thorben Janssen ,You have greal tuto ,this post helped me to understand UUID ,i will read all posts about Hibernate ,you give a great descriptions .
    Best regards

    Reply

  2. I forget the exact version, but we also added support for AUTO generation to be applied to attributes of type UUID and have it automatically map to the UUIDGenerator. You should not need the @GenericGenerator annotation, unless you need to configure the UUID generation strategy

    Reply

  3. Does hibernate automatically know the best way to store the UUID? I’ve seen this suggestion on stackoverflow:

    @Column(name = “id”, columnDefinition = “BINARY(16)”)

    Reply

    1. That depends on the database specific dialect. If you’re using PostgreSQL (as I do in this example), Hibernate PostgreSQL dialect will map it to the PostgreSQL-specific UUID datatype.

      Reply

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