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")
.
This is a very common requirement, so I wrote a very detailed article on this topic.
The first thing you need to do is add the hypersistence-utils
open-source project to your Maven or Gradle configuration file.
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
}
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 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.