postgresqlhibernatespring-data-jpajsonbhibernate-types

How can I store a JSON String into PostgreSQL if the column type is JSONB using JPA?


Didn't Hibernate support this situation?

I have got a way to do that, it is: Use JSONB in JPA

But I cannot judge if it is safe. And I do know I and write the same code by myself, but didn't the official provide some easy way to do that like just add an annotation like @Type(type="jsonb").


Solution

  • This is a very common requirement, so I wrote a very detailed article on this topic.

    Hypersistence Utils project

    The first thing you need to do is add the hypersistence-utils open-source project to your Maven or Gradle configuration file.

    Entity mapping

    Afterward, use the JsonType like this:

    @Entity(name = "Book")
    @Table(name = "book")
    @TypeDef(
        name = "jsonb",
        typeClass = JsonType.class
    )
    public static 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
    }
    

    Persisting the entity

    Now, when you persist 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 will persist the JSON attribute properly:

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

    Fetching the entity

    Fetching the entity works as expected:

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

    So, you don't have to create any custom Hibernate Type since you can find the right type in the hypersistence-utils project.