Hibernate - Using @UuidGenerator Annotation Examples

This tutorial shows you how to use the @UuidGenerator annotation introduced in Hibernate 6.

If you store data in a database, it's very common to use UUID as the primary key where the values are automatically generated. In Hibernate 4 and 5, if you want to define a field whose value is a generated UUID, you have to add @GeneratedValue and @GenericGenerator annotations and define the strategy to be used. Below is an example that generates a random number UUID.

  @Entity
  @Table(name = "items")
  public class Item {
  
    @Id
    @GeneratedValue
    @GenericGenerator(name = "UUID", type = UuidGenerator.class)
    private UUID id;
  
    private String name;

    private BigDecimal price;

    // Constructors, getters, setters, and builder are not included
  }

If you want to use a time based UUID, the annotation is a bit more complex as you have to add the parameters attribute. Fortunately, Hibernate 6 introduced a new annotation called @UuidGenerator that simplifies how to define that a field should use a UUID generator.

Using @UuidGenerator Annotation

To use the annotation, add an import to org.hibernate.annotations.UuidGenerator. It's different from the org.hibernate.id.uuid.UuidGenerator, which is a class that defines the generator. Actually the annotation uses that class as the generator.

Using the annotation is quite simple. You just need to annotate the field with the annotation. It's no longer necessary to use @GeneratedValue or @GenericGenerator. If you define the field and the database column correctly, Hibernate should be able to generate the UUID value automatically when persisting a new entity to the database, even if you don't set it explicitly when creating the object.

  @Entity
  @Table(name = "items")
  public class Item {
  
    @Id
    @UuidGenerator
    private UUID id;
  
    private String name;

    private BigDecimal price;

    // Constructors, getters, setters, and builder are not included
  }

The annotation has an attribute named style whose type is Style enum. The enum has three values:

  • AUTO: Defaults to RANDOM.
  • RANDOM: Generates values using UUID.randomUUID().
  • TIME: Uses a time-based generation strategy according to IETF RFC 4122 with IP address rather than MAC address.

Since the attribute is optional, you are not required to pass it. The default value is AUTO, which defaults to RANDOM. If RANDOM is used, Hibernate will use Java's UUID.randomUUID to generate the UUID values.

The other style is TIME, which uses a time-based generation strategy. According to the implementation note, it may cause a bottleneck as the algorithm needs to synchronize for incrementing an internal count.

Below is an example of how to pass the style attribute to determine which generation algorithm to use.

  @Entity
  @Table(name = "items")
  public class Item {
  
    @Id
    @UuidGenerator(style = UuidGenerator.Style.TIME)
    private UUID id;
  
    // Other columns

    // Constructors, getters, setters, and builder are not included
  }

Now, let's try to test whether the annotation works. First, create a JpaRepository for the Item entity above.

  public interface ItemRepository extends JpaRepository<Item, UUID> {
  }

Then, create a service that creates an object of the entity, but do not set the value for the id field.

  @Service
  public class ItemService {
  
    private final ItemRepository itemRepository;
  
    public ItemService(ItemRepository itemRepository) {
      this.itemRepository = itemRepository;
    }
  
    public void create(ItemRequestDto requestDto) {
      Item item = Item.builder()
          .name(requestDto.getName())
          .price(requestDto.getPrice())
          .build();
  
      this.itemRepository.save(item);
    }
  }

If you try to execute the code, you should find out that the created rows in the database have the id column filled. You can also turn on the Hibernate log to see the generated queries.

  insert into items (name,price,id) values (?,?,?)
  binding parameter [1] as [VARCHAR] - [Test]
  binding parameter [2] as [NUMERIC] - [100]
  binding parameter [3] as [UUID] - [7f000101-8992-1777-8189-922798b00000]

Summary

Hibernate 6 makes it easier for us to define a column whose value is an automatically generated UUID by using the UuidGenerator annotation. The annotation's style attribute can be used to determine the generation algorithm.

You can also read about: