Рубрики
Без рубрики

Сопоставление Java с JSON с помощью JPA и гибернации

Узнайте, как мы можем хранить атрибуты сущностей Java Map в столбцах JSON при использовании JPA, Hibernate и проекта типов Hibernate.

Автор оригинала: Vlad Mihalcea.

Вступление

В этой статье мы рассмотрим, как мы можем хранить атрибуты сущности Java Map в столбцах JSON при использовании JPA, Hibernate и типов Hibernate project.

Хотя вы также можете сохранять атрибуты Java Map сущностей в столбцах PostgreSQL HStore , тип столбца JSON является гораздо более распространенным вариантом, особенно с учетом того, что он работает с другими реляционными базами данных, такими как Oracle, SQL Server или MySQL.

Как вы уже видели, проект Hibernate Types позволяет сопоставлять тип столбца JSON с широким спектром атрибутов сущностей JPA, таких как POJOs, JsonNode , коллекции или String типы объектов Java:

  • Как отобразить атрибуты сущности POJO в формате JSON с помощью JPA и гибернации
  • Как JSON-кодировать атрибуты сущностей как JSON с помощью JPA и гибернации
  • Как сопоставить строковое свойство JPA со столбцом JSON с помощью Hibernate
  • Как сопоставить коллекции JSON с помощью JPA и гибернации

В этой статье показано, что вы также можете сопоставлять типы столбцов JSON с атрибутами сущностей Java Map при использовании JPA и Hibernate.

Зависимость Maven для сопоставления JSON с JPA и гибернацией

Первое, что нам нужно сделать, это добавить зависимость типов гибернации из центрального репозитория Maven. Например, если вы используете Maven, вам необходимо добавить в свой проект следующую зависимость pom.xml файл конфигурации:


    com.vladmihalcea
    hibernate-types-55
    ${hibernate-types.version}

Для более старых версий Hibernate ORM вы можете использовать зависимости hibernate-types-5 , hibernate-types-43 или hibernate-types-4 . В документации Типы гибернации проект содержится более подробная информация о том, какую зависимость следует использовать в зависимости от версии ORM гибернации, используемой вашим проектом.

Модель предметной области

Давайте предположим, что у нас есть следующая книга таблица в нашей реляционной базе данных:

И мы хотим сопоставить его с Книгой сущностью, чей свойства атрибут имеет тип//Map<Строка, строка> :

Сопоставление свойства сущности Java Map со столбцом JSON с помощью JPA и Hibernate

Сущность Book JPA отображается следующим образом:

@Entity(name = "Book")
@Table(name = "book")
@TypeDef(name = "json", typeClass = JsonType.class)
public class Book {

    @Id
    @GeneratedValue
    private Long id;

    @NaturalId
    @Column(length = 15)
    private String isbn;

    @Type(type = "json")
    @Column(columnDefinition = "jsonb")
    private Map properties = new HashMap<>();

    public String getIsbn() {
        return isbn;
    }

    public Book setIsbn(String isbn) {
        this.isbn = isbn;
        return this;
    }

    public Map getProperties() {
        return properties;
    }

    public Book setProperties(Map properties) {
        this.properties = properties;
        return this;
    }

    public Book addProperty(String key, String value) {
        properties.put(key, value);
        return this;
    }
}

Аннотация @TypeDef используется для регистрации типа Json , который обрабатывает типы столбцов JSON при использовании Oracle или PostgreSQL, SQL Server или MySQL.

Свойство isbn использует аннотацию @NaturalID , которая позволяет нам извлекать объект Book по номеру ISBN, не зная его числового идентификатора.

Атрибут свойства имеет тип Map<Строка, строка> , поэтому он использует аннотацию @Type для ссылки на тип json , который мы зарегистрировали ранее с помощью аннотации @TypeDef .

Получатели, установщики, а также метод addProperty утилиты используют API в стиле Fluent для упрощения способа создания Книги экземпляров сущностей.

Время Тестирования

При сохранении следующей Книги сущности:

entityManager.persist(
    new Book()
        .setIsbn("978-9730228236")
        .addProperty("title", "High-Performance Java Persistence")
        .addProperty("author", "Vlad Mihalcea")
        .addProperty("publisher", "Amazon")
        .addProperty("price", "$44.95")
);

Hibernate создает следующую инструкцию SQL INSERT:

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

И при извлечении сущности Book мы видим, что атрибут properties entity правильно извлечен из базы данных:

Book book = entityManager.unwrap(Session.class)
    .bySimpleNaturalId(Book.class)
    .load("978-9730228236");

Map bookProperties = book.getProperties();

assertEquals(
    "High-Performance Java Persistence",
    bookProperties.get("title")
);

assertEquals(
    "Vlad Mihalcea",
    bookProperties.get("author")
);

Потрясающе, правда?

Вывод

Как вы можете видеть, сопоставление свойства сущности Java Map JPA с типом столбца JSON очень просто при использовании типов Hibernate project.

Типы гибернации поддерживают многие нестандартные типы столбцов, а не только JSON. Вы можете использовать его для сопоставления массивов, инициализации, HStore, перечислений, специфичных для PostgreSQL, столбцов, допускающих обнуление Символов , или использовать расширенные экземпляры ResultTransformer .

Если вы используете JPA и Hibernate, то вам определенно следует также использовать типы Hibernate project.