Follow @vlad_mihalcea Imagine having a tool that can automatically detect if you are using JPA and Hibernate properly. Hypersistence Optimizer is that tool!

Introduction

In this article, I want to show you how you can map a String JPA property to a JSON database column using the hibernate-types open-source project.

Although it’s probably more common to use a JsonNode or POJO (Plain Old Java Object) on the Java side, the hibernate-types framework is very flexible and allows you to use a String JPA property type to represent a JSON structure.

Domain Model

Considering we have a book database table that defines a properties column of the jsonb PostgreSQL type.

The associated Book JPA entity can be mapped as follows:

@Entity(name = "Book") @Table(name = "book") @TypeDef( name = "jsonb", typeClass = JsonBinaryType.class ) public class Book { @Id @GeneratedValue private Long id; @NaturalId private String isbn; @Type(type = "jsonb") @Column(columnDefinition = "jsonb") private String properties; //Getters and setters omitted for brevity }

The isbn property is mapped using the Hibernate-specific @NaturalId annotation which allows you to retrieve the entity by its natural identifier.

The properties JPA attribute encodes various book-related properties in a JSON String object. From the JPA @Column definition, we can see that the associated database column is of the type jsonb .

Now, since Hibernate does not provide a native Type to handle JSON database columns, we need to need to use the JsonBinaryType offered by the hibernate-types library.

To use the hibernate-types library in your project, just add the following Maven dependency:

<dependency> <groupId>com.vladmihalcea</groupId> <artifactId>hibernate-types-52</artifactId> <version>${hibernate-types.version}</version> </dependency>

If you’re using an older version of Hibernate, go to the hibernate-types GitHub repository and find the matching hibernate-types dependency for your current Hibernate version.

Testing time

When persisting the following Book entity:

entityManager.persist( new Book() .setIsbn("978-9730228236") .setProperties( "{" + " \"title\": \"High-Performance Java Persistence\"," + " \"author\": \"Vlad Mihalcea\"," + " \"publisher\": \"Amazon\"," + " \"price\": 44.99" + "}" ) );

Hibernate generates the following SQL INSERT statement:

INSERT INTO book ( isbn, properties, id ) VALUES ( '978-9730228236', '{"title":"High-Performance Java Persistence","author":"Vlad Mihalcea","publisher":"Amazon","price":44.99}', 1 )

The JsonBinaryType binds the JSON String using the setObject method of the PreparedStatement object.

Notice the Fluent-style API used when creating the Book entity. For more details about building entities using a Fluent-style API, check out this article.

Now, when fetching the previously persisted Book entity:

Book book = entityManager .unwrap(Session.class) .bySimpleNaturalId(Book.class) .load("978-9730228236"); assertTrue(book.getProperties().contains("\"price\": 44.99"));

We can see that the properties attribute is properly populated by the JsonBinaryType .

Cool, right?

Conclusion

Although creating a custom Hibernate Type is straightforward, it’s much more convenient to use the hibernate-types open-source project since you only need to add one dependency and specify which custom Type you want to use via the @TypeDef annotation.

Insert details about how the information is going to be processed DOWNLOAD NOW