How to implement a custom basic type using Hibernate UserType
Imagine having a tool that can automatically detect JPA and Hibernate performance issues. Wouldn’t that be just awesome?
Well, Hypersistence Optimizer is that tool! And it works with Spring Boot, Spring Framework, Jakarta EE, Java EE, Quarkus, or Play Framework.
So, enjoy spending your time on the things you love rather than fixing performance issues in your production system on a Saturday night!
Introduction
In this article, we are going to see how we can implement a custom type using the Hibernate UserType interface.
If you wonder why you’d ever want to do this, then check out this question.
Our Hibernate user wants a resilient CharacterType
that works with NULL
or empty values. To make it even more interesting, we are going to make it work even if the underlying database column contains more than one character.
Custom type flavors
There are two ways to write a custom Hibernate type:
- Using a
SqlTypeDescriptor
- Using the legacy
UserType
While the former way is usually preferred, as demonstrated by this generic JSON type that works on both MySQL and PostgreSQL, I’m going to use the latter method to demonstrate how the UserTpe
abstraction works.
For the current use case, we are going to use the NullableCharacterType
from the Hypersistence Utils project.
First, you need to add the following dependency to your project:
<dependency> <groupId>io.hypersistence</groupId> <artifactId>hypersistence-utils-hibernate-55</artifactId> <version>${hypersistence-utils.version}</version> </dependency>
For more info about which dependency to use based on the Hibernate version you are using, check out the Hypersistence Utils GitHub repository.
Testing time
Assuming we have an Event
entity, for Hibernate 6, the mapping will look as follows:
@Entity(name = "Event") @Table(name = "event") public class Event { @Id @GeneratedValue private Long id; @Type(NullableCharacterType.class) @Column(name = "event_type") private Character type; }
And for Hibernate 5, like this:
@Entity(name = "Event") @Table(name = "event") public class Event { @Id @GeneratedValue private Long id; @Type(type = "io.hypersistence.utils.hibernate.type.basic.NullableCharacterType") @Column(name = "event_type") private Character type; }
And if we have the following entries in the database:
INSERT INTO event (id, event_type) VALUES (1, 'abc'); INSERT INTO event (id, event_type) VALUES (2, ''); INSERT INTO event (id, event_type) VALUES (3, 'b');
When selecting and logging all event entries:
doInJPA(entityManager -> { List<Event> events = entityManager.createQuery( "select e from Event e", Event.class) .getResultList(); for(Event event : events) { LOGGER.info("Event type: {}", event.getType()); } });
The following output is obtained:
Event type: a Event type: Event type: b
Great!
If you enjoyed this article, I bet you are going to love my Book and Video Courses as well.
Conclusion
Writing a custom type is very easy with the Hibernate UserType.
However, in this case here, you don’t even have to create the NullableCharacterType
.You can just use the Hypersistence Utils project and get this type right out of the box.
