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 toRANDOM
.RANDOM
: Generates values usingUUID.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: