How to map a String JPA property to a JSON column using Hibernate

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


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.

Book table

The associated Book JPA entity can be mapped as follows:

@Entity(name = "Book")
@Table(name = "book")
    name = "jsonb", 
    typeClass = JsonBinaryType.class
public class Book {

    private Long id;

    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:


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:

    new Book()
            "{" +
            "   \"title\": \"High-Performance Java Persistence\"," +
            "   \"author\": \"Vlad Mihalcea\"," +
            "   \"publisher\": \"Amazon\"," +
            "   \"price\": 44.99" +

Hibernate generates the following SQL INSERT statement:

    '{"title":"High-Performance Java Persistence","author":"Vlad Mihalcea","publisher":"Amazon","price":44.99}', 

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

assertTrue(book.getProperties().contains("\"price\": 44.99"));

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

Cool, right?

If you enjoyed this article, I bet you are going to love my Book and Video Courses as well.


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.

Transactions and Concurrency Control eBook

4 Comments on “How to map a String JPA property to a JSON column using Hibernate

  1. I think this article is mistaken in its premise that the hibernate-types library is needed in order to convert a JSON column into a String. Both Postgres and MySQL JDBC drivers will automatically convert JSON columns to a String, meaning the @Type and columnDefinition=… are unnecessary. If additional conversion is needed, such as to a POJO or Jackson’s JsonNode structure, the @Convert JPA annotation can be used. I would be interested if there are other features the hibernate-types provides beyond that for JSON columns.

    • Mapping it as a String will just not work with Hibernate and PostgreSQL as it will call get/setString instead of get/setObject in the JDBC Driver.

      Also, the Hibernate-Types project works even if you have a Pojo instead of String, and it does that for Oracle, SQL Server, PostgreSQL, and MySQL.

      Being used by hundreds of thousands of developers, it provides better guarantees than most in-house converters. Also, most Types work as JPQL parameters and result-set mappings too, which is not the case for JPA Converters.

  2. Thanks for the great tip! It indeed helps a lot. One thing I would like to ask, is it possible to have the json payload structured? For my project, I would like to have fixed structure for json, e.g. (title, isbn, date_issued), no other fields. Can we restrict the payload in some way?

Leave a Reply

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.